JavaScript中this的解析

172 阅读3分钟

this 到底是什么

this是在运行时绑定的,并不是在编写时绑定,他的上下文取决于函数调用时的各种条件,只取决于函数的调用方法。

当一个函数调用时,会创建一个执行上下文,这个上下文会包含函数的调用栈、函数的调用方法和传入的参数等信息。this就是执行上下文的一个属性,在函数的执行过程中用到。

this绑定的绑定

函数的执行过程中调用位置决定了this的绑定对象。

默认绑定

在非严格模式下函数的默认绑定为全局对象(浏览器中为window), 严格模式下的默认绑定为undefined

function foo(){
    console.log(this.a)
}
//变量a的声明默认为全局对象的一个属性
var a = 2;
//非严格模式下this指向了全局对象
foo() //2

隐式的绑定

隐式的绑定的是指函数的调用位置是否有上下文对象,或者说是否被某个对象拥有或者包含。

function foo(){
    console.log(this.a)
}
var obj = {
    a:2,
    foo:foo
}
//foo函数执行过程中this默认绑定为obj对象。则 this.a=obj.a
obj.foo() // 2

隐式丢失

隐式丢失指被隐式的绑定的函数会丢失绑定的对象,从而应用于默认绑定。

function foo(){
    console.log(this.a)
}
var obj = {
    a:2,
    foo:foo
}
var a = "zhang san"//a为全局对象的属性
var bar = obj.foo//将obj.foo引用的函数地址赋值给bar 从而导致bar引用的函数失去隐式绑定
bar()//zhang san

//回调函数丢失this绑定式非常常见的
setTimeout(obj.foo, 100) //zhang san

显示绑定

显示绑定是指利用call(...)apply(...)函数直接指定this的绑定对象。

function foo(){
    console.log(this.a)
}
var obj = {
    a:2,
    foo:foo
}

foo.call(obj)//2

硬绑定

硬绑定是一种显示的强制绑定


function foo(something){
    console.log(this.a,something)
    return this.a + something
}

function bind(fn, obj){
    return function(){
         fun.apply(obj,arguments);
    }
}

var obj = {
    a:2,
}
var bar = bind(foo, obj);
var b = bar(3);//2 3
console.log(b); //5

硬绑定是创建一个包裹函数, 传入所有的参数并返回接收到的所有值。 在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);//2 3
console.log(b); //5

new绑定

使用new来调用函数或者说是发生构造函数调用时,会自动执行下面的操作:

  1. 创建一个全新的对象。
  2. 这个新的对象会被执行原型链接。
  3. 这个新对像会绑定到函数调用的this。
  4. 如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新的对象。

function foo(a){
    this.a = a;
}
var bar = new foo(2);
console.log(bar.a); //2

##优先级 new绑定 > 显示绑定 > 隐式的绑定 > 默认绑定

判断this

  1. new调用?绑定到新创建的对象。
  2. call或者apply (或者bind)调用?绑定到指定的对象。
  3. 由上下文对象调用?绑定到那个上下文对象。
  4. 默认:在严格模式下绑定到undefined,否则绑定到全局对象。