每个函数的this是在调用时被绑定的,完全取决于函数调用的位置!!!!
1.this的绑定规则
(1)默认绑定
function foo(){
console.log( this.a );
}
var a = 2;
foo();
函数没有任何修饰进行调用的,所以在默认情况下会直接将this绑定到全局空间。但这只是在非严格模式下是这样的,严格模式下,this将会是undefined
(2) 隐式绑定
function foo() {
console.log(this.a);
}
var obj = {
a: 42,
foo: foo
};
obj.foo();
此时,obj为this的执行上下文,this指向object
隐式丢失
function foo() {
console.log(this.a);
}
function doFoo(fn) {
fn();
}
var obj = {
a: 2,
foo: foo
};
var a = "oops,global";
doFoo(obj.foo);
foo在doFoo中调用,按照前面的规则,fn()是真正调用foo()的地方,this应该指向doFoo,但是!!!输出结果确实全局变量a,"oops,global"
(3)显示绑定
call与apply
function foo() {
console.log(this.a);
}
var obj = {
a:2
};
foo.call(obj);
这时,this被强制绑定到obj上 ,而且这种绑定一旦绑定就不能修改,es5提供了内置方法Function.prototype.bind,用法如下:
function foo(something) {
console.log(this.a,something);
return this.a + something;
}
var obj = {
a:2
};
var bar = foo.bind(obj);
var b = bar(3);
console.log(b);
bind将this绑定到obj对象,3传给了something,返回的结果是5
(4) new绑定
function foo(a) {
this.a = a;
}
var bar = new foo(2);
console.log(bar.a);
在foo直接为this赋值
2.绑定的优先级
new绑定 > 显式绑定 > 隐式绑定 > 默认绑定
3.一些例外
(1)将null,undefined作为this的绑定对象传入call,apply或者bind会被忽略,实际应用的是默认绑定规则。
但如果把this赋值为null,可能会导致全局变量被修改,因此我们应该采取更加安全的做法,创建一个空对象来代替null
function foo(a,b){
console.log("a:" + a + ",b:" + b);
}
var k = Object.create(null);
foo.apply(k,[2,3]);
var bar = foo.bind(k,2);
bar(3);
(2)间接引用
function foo() {
console.log(this.a);
}
var a = 2;
var o = {a : 3, foo: foo};
var p ={ a: 4};
o.foo();
(p.foo=o.foo)();
赋值表达式 p.foo = o.foo的返回值是foo的引用,所以此时会应用默认绑定
(3)软绑定
和硬绑定不同的是可以修改绑定的值,增强了灵活性
对应的函数是softbind(),用法和bind类似
4.ES6中的this词法
es6中新增了箭头函数,上面的规则已经不再适用
this的指向根据外层作用域来确定
function foo() {
return(a) => {
console.log(this.a);
};
}
var obj1 = {
a:2
}
var obj2 = {
a:3
}
var bar = foo.call(obj1);
bar.call(obj2);
foo绑定到obj1,bar的this也会绑定obj1,输出为2
箭头函数在自己的作用域内没有自己的 this,如果要使用 this ,就会指向定义时所在的作用域的 this 值。
本文详细解析了JavaScript中this的绑定规则,包括默认绑定、隐式绑定、显示绑定及new绑定,并探讨了绑定的优先级、例外情况以及ES6中箭头函数的this词法规则。
441

被折叠的 条评论
为什么被折叠?



