JS判断对象类型

今天来讲讲如何判断 JS 的变量类型。

JS 真不愧是坑爹的语言。

先来个悬念~看完你就懂!!!

const a = new String('aa');
const b = 'aa';
console.log(a instanceof String); // true
console.log(b instanceof String); // flase
  • typeof - 最基本的,有六种返回值,用法 typeof xx/typeof(xx).

检测引用类型值的时候,它的作用不大。

  • instanceof - variable instanceof Object
  • constructor - 写在纸上的发源地,可以被强行篡改。
  • Object.prototype.toString.call(element) - 无法被篡改的祖先,血液里DNA.

一. typeof

主要用于区分基本数据类型和对象。

使用方法: typeof(variable)/typeof variable
使用结果(6种):

  • number
  • boolean
  • string
  • undefined
  • function
  • object

使用示例:

const a = 3;        // number
const b = 'haha';   // string
const c = true;     // boolean
const d = null;     // object
const e = undefined;// undefined
const f = function() {}   // function

总的来说,typeof对于 数组,RegExp(正则),Date等是无力的。


让我们来看一下有一起 JS机制 造成的惊天悬疑案???难道 'aa'和'aa'之间还有种族差别??神秘种族! 基本包装类型!=基本数据类型

实际上还有一种类型叫做:基本包装类型

[基本包装类型有:Number/String/Boolean]

const a = new String('aa');    // object
const b = new Number(3);       // object
const c = new Boolean(true);   // object
const a = 'haha';   // string
const b = 3;        // number
const c = true;     // boolean

实际上呢,这也是基本类型能够拥有方法的原因。短暂蜕变成为基本包装类型 拥有方法 -> 超级赛亚人短暂地获得他们本来没有的实力???哈哈哈

let s1 = 'haha';         // haha
let s2 = s1.substring(2);// ha

在程序中,其实他们的运行过是这个样子的!

let s1 = new String('haha');
let s2 = s1.substring(2);
s1 = null;
  • a.创建 String 类型的一个实例
  • b.在实例上调用指定的方法
  • c.销毁这个实例

经过上面的处理, 基本的字符串类型就变得 和 对象一样了

引用类型和基本包装类型的区别在于对象的生存期。自动创建的基本包装类型实际上只存在于运行的一瞬间。

因为只有一瞬间,所以实际上他们还不是对象,没有办法被添加属性和方法

let s1 = 'some text';
s1.color = 'red';
console.log(s1.color); // undefined

二. instanceof

它主要用于区分 引用类型。

专业解释: instanceof运算符用来判断一个构造函数的prototype属性所指向的对象是否存在另外一个要检测对象的原型链上

const a = new String('aa');
const b = 'aa';
console.log(a instanceof String); // true
console.log(b instanceof String); // flase

上面这个就是我们开头的 悬念了,实际上,看了上面 typeof 相关的解释,这里你是不是也知道了呢!基本包装类型(引用类型)和基本数据类型的差别

使用方法: obj instanceof Object

普通实例(找到他们的父类):

function Person(){};
function Coder(){};
var p = new Person();
var s = new Coder();
console.log(p instanceof Person); // true
console.log(s instanceof Coder); // true

这里是它的一些缺陷的证据(新手跳过)

文艺实例: (这里可以先跳过,看完 高程三 再回来看比较好,比较难)

function Person() {}
console.log(Object instanceof Object);     // true

// 第一个Object的原型链:Object => Object.__proto__ => Function.prototype => Function.prototype.__proto__ => Object.prototype
// 第二个Object的原型:  Object => Object.prototype

console.log(Function instanceof Function); // true

// 第一个Function的原型链:Function => Function.__proto__ => Function.prototype
/ /第二个Function的原型:Function => Function.prototype

console.log(Function instanceof Object);   // true

// Function => Function.__proto__ => Function.prototype => Function.prototype.__proto__ => Object.prototype
// Object => Object.prototype

console.log(Person instanceof Function);      //true

// Person => Person.__proto__ => Function.prototype
// Function => Function.prototype

console.log(String instanceof String);   // false
// String => String.__proto__ => Function.prototype => Function.prototype.__proto__ => Object.prototype
// String的原型链:String => String.prototype

console.log(Boolean instanceof Boolean); // false
// Boolean => Boolean.__proto__ => Function.prototype => Function.prototype.__proto__ => Object.prototype
// Boolean=>Boolean.prototype

console.log(Person instanceof Person); // false
// Person => Person.__proto__ => Function.prototype => Function.prototype.__proto__ => Object.prototype
// Person=>Person.prototype

本意是用来判断 A 是否是 B 的实例对象。这里需要注意。instanceof 检测的是原型。

我们很容易发现问题(通过基本包装类型)。它能够检测出 [] 是 Array 的实例,却不能检测出 [] 不是 Object 的实例。

[] instanceof Array // true
[] instanceof Object // true 不应该啊兄弟

var a = new Number(1);
var b = 1;
a instanceof Number; // true
b instanceof Number; // false 不应啊兄弟

因此,我们用 instanceof 也不能完全精确的判断object类的具体数据类型。
同时,我们发现,使用 Object.prototype.toString.call(x) 时,以上结果都符合预期。

三. constructor

JavaScript中,所有对象都有一个 constructor 属性,它引用初始这个对象的构造函数

constructor就像是写在 纸上 的种族,只要是在纸上的东西,都可能是可以改的,所以,它并不稳定。

constructor 是个属性,在 JS 中,大多数属性是可以被修改的。

// 以下代码运行于 Node v10 环境下
var a = [1, 2];
var b = new Array(3);
var c = 'test';
var d = new String('test');

console.log(d.constructor === String); // true
console.log(c.constructor === String); // true
console.log(b.constructor === Array);  // true
console.log(a.constructor === Array);  // true

也许你会觉得无厘头?谁会这么改,但是:人们有这么做的可能性,我们就应该防范。

var d = new String('test');
String.prototype.constructor = "I'm change.";
console.log(d.constructor); // I'm change
console.log(d.constructor === String); // false

四. 无敌的判断者: Object.prototype.toString.call(element) - 这是源头的源头。

constructor好比我们人类的发源地,比如 亚洲。而这个呢,相当于是地球。

它和下者的差距在这里: https://www.zhihu.com/question/50934612

var d = new String('test');
console.log(Object.prototype.toString.call(d)); // [object String]
var b = new Array(3);
console.log(Object.prototype.toString.call(b)); // [object Array]

complete.

posted @ 2017-07-11 10:06  海客无心x  阅读(234)  评论(0编辑  收藏  举报