ThinkSSL🔒 一键申购 5分钟快速签发 30天无理由退款 购买更放心 广告
  [TOC] 理解 `this` 的第一步就是要明白: `this`既不指向函数自身,也不指向函数的词法作用域; `this`是在运行时进行绑定的,而不是在编写时绑定,它的上下文取决于函数调用时的各种条件; `this`的绑定和函数声明的位置没有任何关系,只取决于函数的调用位置和调用方式; `this`绑定规则有4点:按优先级1到4判断 1. 由`new`调用?绑定到新创建的空对象; 2. 由`call、apply、bind`调用?绑定到指定的参数对象;如`foo.call(obj)` 3. 由上下文对象调用?绑定到这个上下文对象;如`obj.foo()` 4. 默认情况下绑定到全局对象( `window` ),在严格模式下绑定到`undefined`; # 一般情况 1. 情况1:如果一个函数中有 `this` ,但是它没有被上一级的对象所调用,那么 `this` 指向的就是 `window`,这里需要说明的是在 js 的严格模式 中 `this` 指向的不是 `window`,但是我们这里不探讨严格问题(默认的`this`不再是`window`,而是 `undefined`。),你想了解可以自行上网查找。 2. 情况2:如果一个函数中有`this`,这个函数有被上一级的对象所调用,那么`this`指向的就是上一级的对象。 3. 情况3:如果一个函数中有`this`,**这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,`this`指向的也只是它上一级的对象** 例子3可以证明,如果不相信,那么接下来我们继续看几个例子。 ```js var o = { a:10, b:{ a:12, fn:function(){ console.log(this.a); //undefined console.log(this); //window } } } var j = o.b.fn; j(); // 这里在运行时是 window 环境下调用了 fn ``` # 改变this的指向请看[Javascript中apply、call、bind](Javascript中apply、call、bind.md) 解JS构造函数中 `this` 和 `return`: 先看一段代码, ``` function Foo(name,age){ this.name=name; this.age=age; } var foo=new Foo("Tom",14); foo.name; //Tom foo.age; //14 ``` 使用构造函数实例化发生的流程: 1. 建立一个`foo`的空对象。 2. 将构造函数中的`Foo`的`this`指向对象`foo`。 3. `foo`的`__proto__`属性指向`Foo`函数的`prototype`原型。 4. 执行构造函数中的代码。 相对于普通函数,构造函数中的 `this` 是指向实例的,而普通函数调用中的`this` 是指向`windows`的。 构造函数中如果加入了 `return` 的话,分两种情况 ``` function Foo(name,age){ this.name=name; this.age=age; return {name:"Jeff"} } var foo=new Foo("Tom",14); foo.name; //Jeff ``` 1. return 的是五种简单数据类型:`String,Number,Boolean,Null,Undefined`。 这种情况下,忽视`return`值,依然返回this对象。 2. return 的是`Object`。 ```js function fn() { this.user = '追梦子'; return {}; } var a = new fn; console.log(a.user); //undefined ``` ```js function fn() { this.user = '追梦子'; return function(){}; } var a = new fn; console.log(a.user); //undefined ```  这种情况下,不再返回 `this` 对象,而是返回 `return` 语句的返回值。 # 箭头函数中的 this 箭头函数中的 this: *  ES6 中箭头函数( `=>`) 内部没有 `this` 对象,导致 **内部的 `this`就是上一层作用域的 `this`**;默认指向在定义它时所处的对象(宿主对象),另外由于没有 `this`,所以它不能用于定义构造函数。 *  而不是执行时的对象,定义它的时候,可能环境是 `window`,也有可能是其他的。 由于箭头函数不绑定 `this`, 它会捕获其所在(即定义的位置)上下文的 `this` 值, 作为自己的 `this` 值, 1. `this`一旦绑定了上下文,就不会被任何代码改变。 所以 `call() / apply() / bind()` 方法对于箭头函数来说只是传入参数,对它的 `this` 毫无影响。 2. 考虑到 `this` 是词法层面上的,严格模式中与 `this` 相关的规则都将被忽略。(可以忽略是否在严格模式下的影响) ```js const adder = { base : 1, add : function(a) { var f = v => v + this.base return f(a); }, addThruCall: function inFun(a) { var f = v => v + this.base; var b = { base : 2 }; return f.call(b, a); } }; console.log(adder.add(1)); // 输出 2 console.log(adder.addThruCall(1)); // 仍然输出 2(而不是3,其内部的this并没有因为call() 而改变,其this值仍然为函数inFun的this值,指向对象adder ``` ## 箭头函数当做一个方法使用 ```js function test (){ this.a = 'a1'; this.c = { a: 'a2', run: function (){ console.log(this.a) // 这层的作用域按照上述规则 return ()=> { console.log(this.a) // 绑定了上层作用域 } } } } const t = new test() t.c.run()() // 'a2' 'a2' // const f = t.c.run // f()(); // 'undefined' 'undefined' ``` 上例子中,箭头函数中的 `this` 绑定了上层作用域的`this`,只会受到上层作用域的影响!这里的它的上层作用域会受到 # 参考 [彻底理解js中this的指向,不必硬背。](https://www.cnblogs.com/pssp/p/5216085.html) [meaning-of-this-in-node-js-modules-and-functions](https://stackoverflow.com/questions/22770299/meaning-of-this-in-node-js-modules-and-functions)