JavaScript知识点回顾(二十一)——this(六)

234 阅读2分钟

这是我参与8月更文挑战的第二十一天,活动详情查看:8月更文挑战

间接引用

另一个需要注意的是,在编码过程中很有可能传呼机一个函数的“间接引用”,在这种情况下,调用这个函数会应用默认绑定规则。间接引用最容易在赋值时发生:

    function foo(){
        console.log(this.a);
    }
    var a = 2;
    var o = {
        a : 2,
        foo: foo
    };
    var p = {
        a : 4
    };
    o.foo();            //3
    (p.foo = o.foo)();  //2

赋值表达式p.foo = o.foo的返回值是目标函数的引用,因此调用位置是foo()而不是p.foo()或者o.foo()。

软绑定

之前我们体验了硬绑定可以把this强制绑定到指定的对象(除了使用new时)防止函数调用引用默认绑定规则。但是硬绑定大大降低了函数的灵活性,是用硬绑定之后就无法使用隐式或者显式绑定来修改this。于是我们有一种软绑定的方法实现:

    if(!Function.prototype.softBind){
        Function.prototype.softBind = function(obj){
            var fn = this;
            var curried = [].slice.call(arguments,1);
            var bound = function(){
                return fn.apply(
                    (!this||this === (window || global))?obj:this,
                    curried.concat.apply(curried,arguments)
                );
            };
            bound.prototype = Object.create(fn.prototype);
            return bound;
        };
    }

它会对指定的函数进行封装,首先检查调用时的this,如果this绑定到全局对象或者undefined,那就把指定的默认对象obj绑定到this,否则不会修改this。

this词法

我们之前讲的四条规则可以包含所有的正常函数。但是ES6中的箭头函数并不适用这四条规则。箭头函数的this完全根据外层(函数或者全局)作用域来决定。 箭头函数最常用于回调函数中,例如事件处理器或者定时器:

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

箭头函数可以想bind一样确保函数的this被绑定到指定对象,此外,它的重要性还体现在它用更常见的词法作用域取代了传统的this机制。箭头函数会继承外层函数调用的this绑定(无论this绑定到什么)。