this
1. this
-
对于普通函数:指向函数的调用者,即.前面的对象
-
如果没有找到,那么:
- 在非严格模式下,this 指向 window
- 在
"use strict";严格模式下,this 指向 undefined
-
-
这里严格模式,指的是函数体是否处于严格模式下,如果只是调用的位置局部用了严格模式,那还是指向 window
```js function func() { console.log(this.a); } var a = "123"; (function () { "use strict"; func(); // 123 })(); ```-
常见隐式绑定
var a = 'outer'; var obj = { a: 'inner’, foo() { console.log(this.a); } } obj.foo(); // ①inner var bar = obj.foo; bar(); // ②outer setTimeout(obj.foo, 100); // ③outer- 位置 ①,obj.foo(),是 obj 通过.运算符调用了 foo(),所以指向的值 obj。
- 位置 ②,是把 obj.foo 赋值给了 bar,实际上是把 foo 函数赋值给了 bar, bar() 调用的时候,没有调用者,所以使用的是默认绑定规则。
- 位置 ③,是把 obj.foo 赋值给了 setTimeout,实际上调用的还是 foo 函数,调用的时候,没有调用者,所以使用的是默认绑定规则。
-
一个很特别的隐式丢失例子
function func() { console.log(this.a); } var a = 1; var obj1 = { a: 2, func: func }; var obj2 = { a: 3 }; obj1.func(); // 2 (obj2.func = obj1.func)(); // 1 -
对于 setInterval 和 setTimeout,如果他们的参数函数是用普通函数 function() {} 来定义,那么 this 也会指向 window
- 对于老代码,会写很多 bind 来显式修复这个 this 指向,就是函数后面
.bind(this) - 但箭头函数出现后,就不用这么麻烦了
- 对于老代码,会写很多 bind 来显式修复这个 this 指向,就是函数后面
-
-
对于箭头函数:从所在作用域继承 this,自己并没有 this
-
只有函数{ }能构成作用域
-
对象的{ }和 if 语句的{ }都不构成作用域
-
一个很特别的作用域继承例子
function func() { return (a) => { console.log(this.a); }; } var obj1 = { a: 2, }; var obj2 = { a: 3, }; var bar = func.call(obj1); bar.call(obj2); // 2,不是 3 //箭头函数会捕获调用func时的 this,this一旦被确定,就不可更改
-
2. call apply bind
-
相同点:
- 三者都是 Function 原型上的方法:Function.prototype.xxxx()
- 三者都用 this 作为第一个参数,显式绑定,如果不在意绑啥,可传 null
-
不同点:
- 函数调用 call 和 apply 时,返回的是调用执行后的返回值
- 而调用 bind 时,是返回一个被绑定后的新函数,要再加()才能调用执行
- 从参数 2 位置开始,call 接受的是一系列的参数,而 apply 接受的仅是一个数组更方便(其实用 ES6 的...展开运算符,也能直接展开后用 call)
-
比如 Math.max 只是数字的方法,其实对数组也能用
const arr = [1, 2, 3, 5]; Math.max.call(null, ...arr); Math.max.apply(null, arr);