五分钟看懂js关键字this

this是js里面很常用的关键字,而灵活的js也赋予了这个关键字无穷的生命力,相信你也有被它糊弄的时候,我总结了一个6字原则,大部分场合都能清醒分辨this到底指向who,跟大家分享一下,欢迎指正。

谁调用指向谁!

首先介绍一个大boss: window, 他是一个隐形大侠,没有确定的调用者的时候,肯定是它出手, 也就是说,如果一个对象没有显性的调用者时,this指向的就是window。

先看下面的例子:

var x = 10;
function test(){
    console.log("--- test this.x---");
    console.log(this.x);
}
var fruit = {
    x: 20,
    apple: function(){
        console.log("--- apple this.x---");
        console.log(this.x);
    }    
};

fruit.banana = function(){
    var y = 20;
    this.z = 20;
    function pear(){    
        console.log("--- pear this.x---");    
        console.log(this.x);
    }
    console.log("--- banana y---");
    console.log(y);
    console.log("--- banana this.y---");
    console.log(this.y);
    console.log("--- banana this.z---");
    console.log(this.z);
    pear();
}

var myfruit = {
    x: 30
}
myfruit.mylove = fruit.apple;

test();
fruit.apple();
fruit.banana();
test.call(fruit)
myfruit.mylove();
example 1

 运行结果分析:

 1 --- test this.x---
 2 10  // this: window
 3 --- apple this.x---
 4 20 // this: fruit
 5 --- banana y---
 6 20
 7 --- banana this.y---
 8 undefined // this: fruit, we have not assign y to fruit.
 9 --- banana this.z---
10 20 // this: fruit
11 --- pear this.x---
12 10 // this: window
13 --- test this.x---
14 20 // this: fruit, it is fruit to call test.
15 --- apple this.x---
16 30 // this: myfruit

 从上述结果可以看到:

test();
// test()的调用者为隐形boss, this指向window。
fruit.apple();
// apple()的调用者为fruit, this指向fruit。
fruit.banana();
// banana()的调用者为fruit, this 指向fruit。
// 而banana()里面的pear(), 没有显性的调用者,尽管pear()在banana()定义,但是pear()为隐形boss调用,this指向的是window。
test.call(fruit)
// test()在window层面定义,然而实际调用者为fruit,所以this指向fruit。
myfruit.mylove();
// mylove()直接采用了apple()的定义,实际调用者为myfruit,并非fruit,所以this指向myfruit。

综上所述,6字原则可以非常完美的指认this是谁。 这种简单粗暴的方法屡试不爽。谁调用指向谁!! 

温馨提示

在回调函数中使用this, 请谨慎谨慎谨慎。先上example: 

var x = 10;
var fruit = {
    x: 20
};

fruit.slice = function(callback){
    console.log("--- slice ---");
    console.log(this.x);
    console.log("--- callback begin---");
    callback();
}

fruit.slice(function(){
    console.log("--- callback output---");
    console.log(this.x);
    
});
example 2

 输出结果如下:

1 --- slice ---
2 20
3 --- callback begin---
4 --- callback output---
5 10

回调函数里边的this竟然指向window!!!

我也被这个坑得不轻,回调函数里边的this并非指向宿主函数(调用回调函数的函数)的调用者,6字原则在这里还是非常灵光的,callback()调用时有显性调用者吗?没有!!!!因此,this指向是隐形boss window啦。

当然,例子中希望回调函数指向fruit也不难,call可以帮你忙,请看例子。

var x = 10;
var fruit = {
    x: 20
};
fruit.slice = function(callback){
    console.log("--- slice ---");
    console.log(this.x);
    console.log("--- callback begin---");
    callback.call(this);
}

fruit.slice(function(){
    console.log("--- callback output---");
    console.log(this.x);
    
});
example 3

妥妥输出:

--- slice ---
20
--- callback begin---
--- callback output---
20

再强调一遍,6字原则在确定js关键字this是谁的问题上屡试不爽, 谁调用指向谁!言下之意,没有调用者就是隐形boss window

细心的看官也许会问, 第一个例子中的pear(), 既然里边的this指向window, 为什么不能在全局域中使用window.pear() or pear()呢?

Good question!

把这个问题用代码还原其实是这样:

var fruit = {};
fruit.banana = function(){
    function pear(){}
}

// 这样调用会出错咯
pear();
// 这样调用也不行
window.pear();

 这两种方式调用都有exception,因为pear()只能在banana里面assign给banana的变量,或者在banana内部调用。

这样调用是对的;

var fruit = {};
fruit.banana = function(){
    this.callPear = pear; // assign 给callPear
    function pear(){ console.log("I am pear!");}
   pear(); // 内部调用
}

var instant = new fruit.banana();
instant.callPear();

 这涉及另外一个话题,作用域,scope!下次再跟大家详细分享scope。

原文地址:https://www.cnblogs.com/haihai1203/p/5695920.html