初衷:
关于typeof vs instanceof、=== vs ==
的介绍。
过程:
1.1 typeof
会判断数据类型会返回一个字符串
typeof
来判断基本数据类型是可以的,但有例外:typeof null
结果却为"object"
.在数组,正则,日期,对象上的判断上都是返回object
。因此使用它并没有那么准确。
1.2 想要判断一个对象的具体类型可以考虑用 instanceof
L instanceof R
主要原理:检测左侧的L __proto__
原型链上,是否存在右侧的R prototype
原型。
1.3 区分对象与数组的最好办法:Array.isArray()
以及Object.prototype.toString.call()
方法
判断数据类型更为精确的方法:Object.prototype.toString.call()
Object.prototype.toString.call(1); // "[object Number]"
Object.prototype.toString.call('aaa'); // "[object String]"
Object.prototype.toString.call({name:'yeye'}); // "[object Object]"
Object.prototype.toString.call([2,5,8]); // "[object Array]"
Object.prototype.toString.call(false); // "[object Boolean]"
Object.prototype.toString.call(() => {}); // "[object Function]"
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call(undefined); // "[object Undefined]"
Object.prototype.toString.call(Symbol(2)); // "[object Symbol]"
复制代码
利用Object.prototype.toString.call(1).slice(8,-1);
便可得到其真正的类型"Number"
.其他的以此类推。
1.4 ===
VS ==
===
“严格相等”;比较类型是否相同、值是否相等。如果比较的双方是都是对象类型,只有指向同一个对象,才能严格相等。
==
“等于”;,如果类型不同,会先进行隐式类型转换,转换成相同类型再比较,这时与===相同.
一些练习题:
var y = 1, x = y = typeof x;
x;
复制代码
1.结果:undefined
js中的赋值语句是从右边着手看起:y = typeof x
,x
只定义为赋值,便显示undefined
;typeof undefined
结果为undefined
,故而x=undefined
.
表达式是从右往左执行的,执行typeof x
时,x
只声明但未赋值,执行结果为undefined
,所以x=y=undefined
.
(function f(f){
return typeof f();
})(function(){ return 1; });
复制代码
2.结果:number
传入的参数ffunction(){ return 1; }
,返回数字1
,typeof f() typeof 1
返回number
.
var foo = {
bar: function() { return this.baz; },
baz: 1
};
(function(){
return typeof arguments[0]();
})(foo.bar);
复制代码
3.结果:undefined
this永远指向函数执行时的上下文,而不是定义时的.foo.ba
r可以视为函数function(){ return this.baz; }
的函数名,它通过arguments[0]
传到自执行函数里面。也就是说foo.bar
就是arguments[0]
,现在这个foo.bar
看作一个整体,视为一个函数名,那么这个名为foo.bar
的函数是在window
下调用的,window
下面没有baz
,因此返回的应该是"undefined"
。
var foo = {
bar: function(){ return this.baz; },
baz: 1
}
typeof (f = foo.bar)();
复制代码
4.结果:undefined
foo.bar
作为一个整体赋给了f
,那么f
调用的时候,也还是在window
下调用的。this
指向是window
,window
下面没有baz
,因此应选"undefined"
.
var f = (function f(){ return "1"; }, function g(){ return 2; })();
typeof f;
复制代码
5.结果:number
分组选择符:(),只要记住,走的都是最后一个。
var x = 1;
if (function f(){}) {
x += typeof f;
}
x;
复制代码
6.结果:"1undefined"
函数声明是不能写到运算符的运算过程当中,例如if
的括号或者for
循环的括号中。函数写到这里面的话,函数名字就找不到了。函数声明必须是全局的或局部的,不能写到运算当中。所以typeof
后面的f
是找不到的,因此typeof f
返回的是"undefined"
。
(function(foo){
return typeof foo.bar;
})({ foo: { bar: 1 } });
复制代码
7.结果:undefined
形参foo
指的是{ foo: { bar: 1 } }
这个整体,在typeof foo.bar;
中的这个foo
下面只有一个foo
属性,并没有bar
这个属性.
(function(){
return typeof arguments;
})();
复制代码
8.结果:"Object"
arguments
是一个实参的集合,它是一个对象.
var f = function g(){ return 23; };
typeof g();
复制代码
9.结果:Error
如果第一行中的g不写的话,那么就是一个函数赋给了一个变量,这叫作“函数表达式”。这里这个函数是有名字的,因此叫作“有名的函数表达式”。多了这个名字,这种写法就是不规范的。这个f是能够找到的,但是这个g()在有些浏览器下是找不到的。因此选第四项Error`
(function(x){
delete x;
return x;
})(1);
复制代码
10.结果:1
delete不能删除变量,也不能删除参数。它只能删除一个对象下面的属性。
var x = [typeof x, typeof y][1];
typeof typeof x;
复制代码
11.结果:string
不管x是什么,typeof x返回的必然是字符串.
(function f(){
function f(){return 1;}
return f();
function f(){return 2;}
})()
复制代码
12.结果:2
函数声明是会预解析的,因此在return f();
这一句还没有执行的时候,上面和下面的这两句就已经执行完毕了。后面把前面的覆盖了,因此在return f();
这一句执行的时候,这个f
已经是下面的那个函数了.
function f(){return f;}
new f() instanceof f;
复制代码
13.结果:false
结语:
在看相关文章时,无意间发现一篇自我感觉非常不错的, 这里会更好看,本文中出现的部分也是来源于此。