[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)
- 步入JavaScript的世界
- 二进制运算
- JavaScript 的版本是怎么回事?
- JavaScript和DOM的产生与发展
- DOM事件处理
- js的并行加载与顺序执行
- 正则表达式
- 当遇上this时
- Javascript中apply、call、bind
- JavaScript的编译过程与运行机制
- 执行上下文(Execution Context)
- javascript 作用域
- 分组中的函数表达式
- JS之constructor属性
- Javascript 按位取反运算符 (~)
- EvenLoop 事件循环
- 异步编程
- JavaScript的九个思维导图
- JavaScript奇淫技巧
- JavaScript:shim和polyfill
- ===值得关注的库===
- ==文章==
- JavaScript框架
- Angular 1.x
- 启动引导过程
- $scope作用域
- $q与promise
- ngRoute 和 ui-router
- 双向数据绑定
- 规范和性能优化
- 自定义指令
- Angular 事件
- lodash
- Test