this全面解析

89 阅读1分钟
默认绑定
function foo () {
    console.log(this.a)
}
var a = 2
foo() // 2
​
function foo () {
    "use strict";
    console.log(this.a)
}
var a = 2
foo() // TypeError: this is undefined
隐式绑定
function foo() {
    console.log(this.a)
}
var obj = {
    a: 2,
    foo,
}
obj.foo() // 2var obj1 = {
    a: 2,
    obj2,
}
var obj2 = {
    a: 42,
    foo
}
obj1.obj2.foo() // 42var bar = obj.foo
var a = "oops, global"
bar() // "oops, global"setTimeout(obj.foo, 100) //"oops, global"
显示绑定
function foo(something) {
    console.log(this.a, something);
    return this.a + something;
}
// 简单辅助函数
function bind(fn, obj) {
    return function() {
        return fn.apply(obj, arguments)
    }
}
var obj = {
    a: 2;
}
var bar = bind( foo, obj );
var b = bar(3); // 2 3
console.log(b) // 5
new绑定
  1. 创建一个全新对象
  2. 新对象执行原型连接
  3. 新对象绑定到函数调用的this
  4. 如果函数没有返回其他对象,那么表达式中的函数调用返回这个新对象
function foo(a) {
    this.a = a;
}
var bar = new foo(2)
console.log(bar.a) // 2
忽略this

foo.bind(null, 2)通过null来忽略this绑定可能产生副作用。(比如修改全局变量)

一种更安全方法时绑定一个DMZ(demilitarized zone 非军事区)一个空的非委托对象

function foo(a, b) {
    console.log("a: " + a + ", b: " + b);
}
// DMZ对象
var Q = Object.create(null)
foo.apply(Q, [2, 3]) // a: 2, b: 3
var bar = foo.bind(Q, 2)
bar(3) // a: 2, b: 3
软绑定

首先检查调用的this,如果this绑定到全局对象或者undefined,那就把指定的默认对象obj绑定到this,否则不会修改this

if(!Function.prototype.softBind) {
    Function.prototype.softBind = function(obj) {
        var fn = this;
        var crried = [].slice.call(arguments, 1)
        var bound = function () {
            return fn.apply(
            (!this || this === (window || global)) ?
                obj : this
            curried.concat.aplly(curried, arguments)
            );
        };
        bound.prototype = Object.create(fn.prototype);
        return bound;
    }
}
function foo() {
    console.log("name" + this.name)
}
var obj = {name: "obj"},
    obj2 = {name: "obj2"},
    obj3 = {name: "obj3"};
var fooOBJ = foo.softBind(obj)
fooOBj() // name: obj
​
obj2.foo = foo.softBind(obj);
obj2.foo(); // name: obj2
​
fooOBJ.call(obj3)
​
setTimeout(obj2.foo, 10);// name: obj软绑定
箭头函数

箭头函数回继承外层函数调用的this绑定(无论this绑定到什么)这个以下相同

function foo() {
    var self = this;
    setTimeout(function() {
        console.log(self.a)
    }, 100)
}
var obj = {
    a: 2
}
foo.call(obj); // 2