JavaScript this关键字

108 阅读2分钟

this

JavaScript的关键字this,是对象自动生成一个内部对象,只能在对象内部使用。随着函数的调用,this指向调用该函数的对象。

this绑定方式,优先级从上到下

new > call/apply/bind(显示绑定) > (上下文)对象(隐式绑定) > (window)默认绑定

1. new

js不存在constructor,所以new修饰的函数是函数的构造调用, js的new作了以下工作:

  1. 创建一个新对象
  2. 把这个新对象的__proto__指向原函数的prototype(即继承原函数的原型)
  3. 将这个新对象绑定到此函数的this
  4. 返回新对象,如果函数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