1. 严格模式this绑定为undefined
非严格模式下,以下调用方式中,this
绑定为全局对象window
,
function f() {
console.log(this); // window
}
f();
而在严格模式下,this
绑定为undefined
。
function f() {
'use strict';
console.log(this); // undefined
}
f();
值得注意是的,只有this
处于严格模式中,才会绑定为undefined
,
与f
被调用的位置是否处于严格模式无关。
function f() {
console.log(this); // window
}
(function () {
'use strict';
f(); // 在严格模式中调用f
})();
2. bind和new的优先级
function f() {
return this;
}
const g = f.bind({ a: 1 });
g(); // {a:1}
const obj = new g;
// instanceof都为true
console.assert(obj instanceof f);
console.assert(obj instanceof g);
// Symbol.hasInstance
console.assert(f[Symbol.hasInstance](obj));
console.assert(g[Symbol.hasInstance](obj));
// f为constructor
console.assert(obj.constructor === f);
console.assert(obj.constructor !== g);
// f的prototype在obj的原型链上
console.assert(obj.__proto__ === f.prototype);
// g的prototype为undefined
console.assert(g.prototype === undefined);
可见new
对this
的影响比bind
优先级要高,
g
虽然通过bind
绑定了this
指向的对象为{a:1}
,
但是使用new g
调用的时候,this
仍然指向以f
为构造函数的实例。
值得注意的有两点,
(1)bind
之后,g.prototype
为undefined
。
(2)new g
返回的对象obj
,使用instanceof
判断f
和g
都为true
,
原因就在于,V instanceof target
首先会先用target[Symbol.hasInstance](V)
来判断,
然后再判断,target.prototype
是否在V
的原型链上,参考ECMAScript Language Specification
但是bind
的柯里化作用还是有用的,
function f(p1, p2) {
this.v = p1 + p2;
}
const g = f.bind(null, 'x');
const obj = new g('y');
console.log(obj.v); // xy
3. call null会将this绑定为全局对象
使用call
或者apply
,将this
绑定为null
或undefined
并不会凑效,
此时,this
将绑定为全局对象。
function f(){
return this;
}
f.call(null); // window
f.call(undefined); // window
然而,在严格模式下,this
将绑定为null
或undefined
,
function f(){
'use strict';
return this;
}
f.call(null); // window
f.call(undefined); // window
值得一提的是,在非严格模式下,f.call(1);
会自动将1
包装成new Number(1)
,
然后this
指向的是这个包装对象。
而在严格模式下,f.call(1);
会将this
绑定为1
。
function f(){
return this;
}
function g(){
'use strict';
return this;
}
f.call(1); // Number {1}
g.call(1); // 1
4. Object.create(null)与{}的区别
const a = Object.create(null);
console.assert(a.__proto__ === undefined);
// 会创建一个原型为undefined的对象
const b = {};
console.assert(b.__proto__ === Object.prototype);
b={}
相当于b=new Object
,因此,b
是Object
构造函数的实例。
而Object.create(null)
会创建一个空对象,它没有原型。
注意,Object.create(undefined);
会报错,
Uncaught TypeError: Object prototype may only be an Object or null: undefined
5. 赋值表达式的返回值
window.a = 0;
function f(){
return this.a;
}
const obj1 = {
a:1,
f,
};
const obj2 = {
a:2,
};
(obj2.f=obj1.f)(); // 0
赋值表达式的返回值是函数的引用,因此相当于f()
,
而不是obj1.f()
,也不是obj2.f()
。
网友评论