浏览器与Node 中的this

上午在复习闭包的时候,又看了一下阮一峰老师的那篇 学习Javascript闭包(Closure),内容不多,讲得也很清晰。但是最后的两个题目引发了较多的争议,看好多人评论说第一个题目实际上是this 指针的问题。于是亲自去实践下,再结合其他几篇文章,又跑去研究一下浏览器和Node 中的this 指针的问题,最终总结整理出一点东西,写在下面。

1. 两个题目

首先来看一下那两个题目,第一题:

var name = "The Window";
var object = {
  name : "My Object",
  getName : function() {
    // 返回一个匿名函数
    return function() {
      return this.name;
    };
  }
};
console.log(object.getName()());

这一段代码在浏览器下运行的结果是"The Window",在node 环境下运行结果是undefined,为啥?后面再说,先把两个题目看完,第二题:

var name = "The Window";
var object = {
  name : "My Object",
  getName : function() {
    var that = this;
    return function() {
      return that.name;
    };
  }
};
console.log(object.getName()());

这段代码在浏览器和node 环境下运行结果都是"My Object",这段代码就比较容易理解了,简单解释一下。这里先引用一下this 的定义:

this是包含它的函数作为方法被调用时所属的对象

也就是说that 在这里所代表的是object 对象,所以that.name 的值为"My Object"。

2. Node 中的this

(1)Node 全局对象global

第一道题目中node 环境下的输出结果让我很疑惑,所以又去找其他相关的代码来尝试和猜想,结果发现以下代码:

name = 'The Window';
var object = {
  name : 'My Object',
  getName : function() {
    return function() {
      return this.name;
    };
  }
};
console.log(object.getName()());  // The Window

可以看到,这段代码与第一道题目中的代码相似度高达96%(以肉眼可见的优势超越了oppo find x 的93.8% 的屏占比),但是在node 环境下运行的结果却截然不同。为啥会这样呢?看了好多遍发现,两者的差别就在于,上面的代码的第一行没有var 声明。于是可以得到一个阶段性结论:node 环境下未添加var 声明的变量挂载在全局对象(global)上,而object 中的getName 方法中返回匿名函数中的this 指向全局对象,所以此时能得到输出"The Window"。这个结论验证起来也很简单,在上面的代码中添加一行:

console.log(global.name);  // The Window

(2)Node 环境下全局的this 指向什么?

紧接着,我又尝试了以下的代码:

this.name = 'The Window'
var object = {
  name : 'My Object',
  getName : function() {
    return function() {
      return this.name;
    };
  }
};
console.log(object.getName()());  // undefined

结果正如代码中的备注所示,undefined。从结果来看,最正确的解释就是node 环境下global  != 全局this。那node 环境下全局的this 是什么呢?打印了一下看看:

console.log(this);  // {}

原来,node 下全局this 指向一个空对象,那这么做的意义是什么呢?我在 https://www.cnblogs.com/pssp/p/5321506.html 这里找到了答案:

this.name = 'The Window';
console.log(module.exports);  // { name: 'The Window' }

结合node 的模块化机制,我们可以了解到,原来node 全局的this 指向的是当前对象,是我们使用module.exports 时会导出的东西。

3. 结论

综合上面两点探讨,可以得到以下结论:

(1)浏览器环境下,不使用var 声明和在全局使用this 声明的变量都会挂载到Window 对象上。

(2)Node 环境下,不使用var 声明的变量被挂载到全局对象global 中,可以被匿名函数中的this 访问到;使用全局this 声明的变量会放到module.exports 对象中作为当前文件导出值的一部分。

至此,题目中要讨论的东西就已经讨论完了,下面要讲的一个点是之前一直有点模糊的问题,也是关于this 的指向问题。


4. new 还是不new?

一个很经典的问题,如果有以下代码:

var test = function() {
  this.str = 'inner';
  console.log(this);
}

test();
new test();

分别带new 和不带new 调用的时候有什么区别。从打印结果就可以看到,两者的this 指向不同,不带new 的时候this 指向全局对象,带new 的时候this 指向test。

要传递的信息其实不是很多,不知道表达清楚没有,有什么需要改进的地方可以在评论区留言,哈哈~

猜你喜欢

转载自blog.csdn.net/qq_33594380/article/details/82254834
今日推荐