今天早上看到公众号推送了阮一峰老师的文章JavaScript 的 this 原理,文章不是很长于是研究了一下。

看完自己的总结如下:

this

  • this 指向函数运行时所在的环境。
  • 函数运行在对象内,this 就指向该对象
  • 运行在全局环境,this 就指向全局环境
  • js 允许函数体内部引用当前环境外的其他变量,由于函数可以在不同运行环境执行,“当前环境外的其他变量”就是指“不同运行环境中的变量” ,那么这个时候就需要有一种机制,能够在函数体内部获得当前的运行环境,所以 ==this== 就应运而生了。

看到 ==js 允许函数体内部引用当前环境外的其他变量== 想到之前自己总结过的关于作用域的知识点:

作用域

  • 函数定义的时候就被确定了作用域,与它在什么地方被调用执行无关
  • 当前作用域没有定义的变量,即自由变量,会到父级作用域中查找,和执行作用域无关;

令我产生困惑的两句话:

  • 函数定义的时候就被确定了作用域,和执行作用域无关
  • js 允许函数体内部引用当前环境外的其他变量

这里的 ==执行作用域== 与下文的 ==当前环境外的其他变量== 如何理解或者做区分?

翻阅红宝书(第三版)p73,执行环境是 js 中最为重要的一个概念,总结如下:

  1. 函数的运行环境即其执行环境
  2. 每个函数都有自己的执行环境,执行环境定义了函数有权访问的其他数据,保存在变量对象之中。
  3. 当代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链决定了访问变量对象的顺序。
  4. this 可以指向不同的运行环境,这里的运行环境本质上指的是对象,可以是内建对象、自定义对象或者全局对象。
  5. 函数定义时就被确定了作用域,这个作用域决定了其访问变量对象的顺序。而函数可以在不同环境被执行,这里的 ==不同环境== (可能是外层函数或者全局环境下)的作用域才是执行作用域。
  6. 所以 执行作用域 可以理解为 函数执行位置外部函数或者全局环境的作用域, 与函数自己的作用域(声明时就被确定了) 完全是两码事
  7. 当前环境外的其他变量即函数自己作用域外的其他变量
  8. 函数要想引用 当前环境外的其他变量 只能用 this ,this 指向当前运行环境,运行在对象内就指向对象,运行在全局环境就指向全局对象
  9. 咦,我自己怎么也有点乱。。

运行在全局环境的 this

众所周知,浏览器环境下 全局环境下的 this 就是 window,没有一点问题

// 浏览器环境下
var a = 'a'
this.b = 'b'
console.log(this.a)  // a
console.log(b)      // b
console.log(this===window) // true

但是...

// node 环境下
var x = 'xx'
global.y = 'yy'
// node 环境下输出
console.log(y);   // yy  global 属性挂载到了全局环境, 
console.log(global.x) // undefined   全局环境中定义的x 变量并没有挂载到顶层对象global对象中
console.log(this === global)  // false 
console.log(JSON.stringify(this))// {}  空对象,并不是 global

查阅MDN发现:

// node 环境下
function f1() {
    return this
}

console.log(f1() === global) // true  
console.log(this === global) // false

node 环境下只有定义在函数内部的 this 才指向 global ?
那么, node 环境下 this 到底指向什么?经过和导师的沟通
终于发现

// node 环境下
this.num = '10'
global.test = '12'
console.log(module.exports) // {num: "10"}    
console.log(this===module.exports) // true

那么 node 环境下 this 为什么指向 module.exports 这和模块化的设计又有什么关系?

发人深思...

天色已晚,且听下回分解。


Stanny2017
4 声望1 粉丝

« 上一篇
co 函数库