浓缩解读前端系列书籍一周一章前端书

一周一章前端书·第7周:《你不知道的JavaScript(上)》

2017-11-11  本文已影响3人  梁同学de自言自语

第2章:this全面解析

2.1 调用位置

function baz(){
    //当前位置是baz
    console.log("my name is baz");
    //baz中调用bar
    bar();
}

function bar(){
    //当前位置是bar
    console.log("my name is bar");
    //bar中调用foo
    foo();
}

function foo(){
    //当前位置是foo
    console.log("my name is foo");
}

//window下调用baz
baz();

/* 
 * 所以foo的调用栈(链)就是:
 * window -> baz -> bar -> foo
 * /

2.2 绑定规则

2.2.1 默认绑定

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

注意:如果 函数内使用严格模式(strict mode) ,是不能将全局对象用于默认绑定的,最终this会绑定到undefined上。举例说明:

var a = 2;
function foo(){ 
  "use strict";
  console.log(this.a);
}
foo();    //输出 TypeError : this is undefined

在严格模式下调用函数 ,则不影响默认绑定。举例说明:

var a = 2;
function foo(){
  console.log(this.a);
}
(function(){
  "use strict";
  foo():  // 输出2
)();

由于我们可能会使用众多第三方库,所以代码中可能会混合使用strict模式和非strict模式,因此一定要注意这类的兼容性问题。

2.2.2 隐式绑定

var obj = {
    a : 2,
    foo : foo
}

function foo(){
    console.log(this.a);
}

obj.foo();  // 输出 2
function foo(){
    console.log(this.a);
}

var obj1 = {
    a : 2,
    obj2 : {
        a : 42,
        foo : foo
    }
}

obj1.obj2.foo();    //输出 42
var a = 'oops,global';
var bar = obj1.obj2.foo;

function runFoo(){
    obj1.obj2.foo();
}

// 都是输出 'oops,global'
bar();  
runfoo();   
setTimeout(obj1.obj2.foo,100);

2.2.3 显示绑定

function foo(){
    console.log(this.a);
}
var obj = {
    a : 2
};
foo.call(obj);  // 输出 2
function foo(){
    console.log(this.a);
}

var obj = {
    a : 2
};

var bar = function(){
    foo.call(obj);
};

bar();  // 2
setTimeout(bar,100);

//硬绑定不能再修改它的this
bar.call(window);   // 2
function foo(something){
    console.log(this.a,something);
    return this.a + something;
}
var obj = {
    a : 2
}
var bar = function(){
    return foo.apply(obj,arguments);
};


var b = bar(3); // 2 3
console.log(b); // 5
function foo(something){
    cosnole.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
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
function foo(el){
    console.log(el,this.id);
}
var obj = {
    id : 'awesome'
}
[1,2,3].forEach(foo,obj);

2.2.4 new绑定

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

2.3 优先级

function foo(){
    console.log(this.a);
}
var obj1 = {
    a : 2,
    foo : foo
}
var obj2 = {
    a : 3,
    foo : foo
}

obj1.foo(); //2
obj2.foo(); //3

obj1.foo.call(obj2);    // 3
obj2.foo.call(obj1);    // 3
function foo(something){
    this.a = something;
}
var obj1 = {
    foo : foo
}
var obj2 = {}

obj1.foo(2);
console.log(obj1.a);    //2

obj1.foo.call(obj2,3);
console.log(obj2.a);    //3

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

var bar = foo.bind(obj1);
bar(2);
console.log(obj1.a);    //2

var baz = new bar(3);
console.log(obj1.a);    // 2
console.log(baz.a);     // 3
function foo(p1,p2){
    this.val = p1 + p2;
}

var bar = foo.bind(null,"p1");
var baz = new bar("p2");
baz.val;    //p1p2

2.4 绑定例外

2.4.1 被忽略的this

function foo(){
    console.log(this.a);
}
var a = 2;
foo.call(null); // 2
function foo(a,b){
    console.log('a:'+a+'b:'+b);
}

foo.apply(null,[2,3]); // a:2,b:3

//先预先传入参数a
var bar = foo.bind(null,2);
//调用时再传入参数b
bar(3); // a:2,b:3
function foo(a,b){
    console.log('a:'+a+'b:'+b);
}

var o = Object.create(null);
foo.apply(o,[2,3]); // a:2,b:3

//先预先传入参数a
var bar = foo.bind(o,2);
//调用时再传入参数b
bar(3); // a:2,b:3

2.4.2 间接引用

function foo(){
    console.log(this.a);
}

var a = 2;
var o = {
    a : 3,
    foo : foo
}
var p = { 
    a : 4
}

o.foo(); // 3
(function(){
    p.foo = o.foo
})();   // 2

2.4.3 软绑定

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;
    }
}

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);  // name : obj3

setTimeout(obj2.foo,10);    // name : obj

2.5 this词法

function foo(){
    return (a) => {
        console.log(this.a);
    }
}

var obj1 = {
    a : 2
}

var obj2 = {
    a : 3
}

var bar = foo.call(obj1);
bar.call(obj2); // 2 , 不是 3 !
function foo(){
    setTimeout(() => {
        console.log(this.a);
    },100);
}
var obj = {
    a : 2
};
foo.call(obj); // 2

2.6 小结

上一篇 下一篇

猜你喜欢

热点阅读