this
JavaScript的关键字this,是对象自动生成一个内部对象,只能在对象内部使用。随着函数的调用,this指向调用该函数的对象。
this绑定方式,优先级从上到下
new > call/apply/bind(显示绑定) > (上下文)对象(隐式绑定) > (window)默认绑定
1. new
js不存在constructor,所以new修饰的函数是函数的构造调用, js的new作了以下工作:
- 创建一个新对象
- 把这个新对象的
__proto__指向原函数的prototype(即继承原函数的原型) - 将这个新对象绑定到此函数的
this上 - 返回新对象,如果函数
return了一个对象类型,那么将无法返回新对象,将丢失绑定this的新对象
function foo() {
this.a = 5;
console.log(this);
}
foo(); // this是window,window.a = 5,默认绑定this->window
var obj = new foo(); // foo{a: 5} 创建的新对象,默认名为函数名
// 等价于 var foo = {a: 10}; var obj = foo;
如果函数返回了对象类型,那么将无法返回新对象,丢失this
function foo() {
this.a = 5;
return {};
}
var obj = new foo(); // 等价于 var foo = {}; var obj = foo;
console.log(obj.a); // undefined
2. call/apply/bind 显示绑定
修改函数的this指向,第一个参数是设置 this 对象, call/apply 立刻执行函数, bind将绑定好this的函数返回
call(thisArg, arg1, arg2, ...)apply(thisArg, [args])bind(thisArg): Function
function foo() {
console.log(this.a);
}
foo.call({a: 5}); // 5
foo.apply({a: 3}); // 3
foo.bind({a: 1})(); // 1
3. 隐式绑定
调用函数的是谁,this就指向谁
function foo() {
console.log(this.a);
}
var obj = {
a: 5,
foo: foo
}
foo(); // undefined
obj.foo(); // 5
4. 默认绑定
默认绑定到 window上,严格模式下是 undefined,如上示例中的 foo();
5. 箭头函数
- 箭头函数不使用前面的四种绑定,完全根据外部作用域来决定
this - 箭头函数的
this绑定无法被修改
var obj = {
that: this,
bar: function() {
return () => {
console.log(this);
}
},
baz: () => {
console.log(this);
}
}
console.log(obj.that); // window, obj当前的作用域是window, that === window
obj.bar()(); // func有自己的函数作用域,将箭头函数绑定到当前对象上obj,箭头函数自动绑定函数所在的作用域obj
obj,baz(); // 默认绑定的父级作用域就是window
练习
1
var x = 10;
var obj = {
x: 20,
foo: function() {
console.log(this.x); // 20
var bar = function() {
console.log(this.x); // 10
}
bar();
}
}
obj.foo();
2
function foo(arg) {
this.a = arg;
return this;
}
// foo 默认绑定,this指向了window,函数里等价于 foo() { window.a = 1; return window; }
// window.a = window
var a = foo(1);
// window.a = 10
// window.b = window
var b = foo(10);
console.log(a.a); // window
console.log(b.a); // 10