this 是执行上下文环境的一个属性,解析器在调用函数时会将 this 做为参数隐式传入函数内部,根据函数调用方式的不同 this 会指向不同的对象(即函数执行时决定)

  • this 指向最后调用它的对象

    四种绑定规则

    1. 默认绑定 ->> 以函数形式调用时

    this 永远执行 window

  1. window.auntie = '漂亮阿姨';
  2. function callAuntie () {
  3. console.log('call:', this.auntie);
  4. // function 內的 function
  5. function callAgainAuntie () {
  6. console.log('call again:', this.auntie);
  7. }
  8. callAgainAuntie();
  9. }
  10. callAuntie();
  11. //无论在哪一层,纯粹的调用方式 this 都会指向 window。

顶层对象

顶层对象(浏览器环境指 window、Node.js 环境指 Global)的属性和全局变量属性的赋值是相等价的,使用 var 和 function 声明的是顶层对象的属性,而 let 就属于 ES6 规范了,但是 ES6 规范中 let、const、class 这些声明的全局变量,不再属于顶层对象的属性。

  1. function demo(){
  2. console.log(this.a); // 1
  3. }
  4. var a = 1;
  5. demo();
  1. function demo(){
  2. console.log(this.a); // undefined
  3. }
  4. let a = 1;
  5. demo();

2.隐式绑定 ->> 以方法的形式调用

this 是调用方法的对象

  1. function callName() {
  2. console.log(this.name);
  3. }
  4. var name = '全域阿婆';
  5. var auntie = {
  6. name: '漂亮阿姨',
  7. callName: callName
  8. // 這裡的 function 指向全域的 function,但不重要
  9. }
  10. callName() // '全域阿婆'
  11. auntie.callName() // '漂亮阿姨',以方法的形式调用时,this是调用方法的对象
  1. function child() {
  2. console.log(this.name);
  3. }
  4. let parent = {
  5. name: 'zhangsan',
  6. child,
  7. }
  8. let parent2 = parent.child;
  9. var name = 'lisi';
  10. parent2(); // 'lisi'

3.new绑定 ->> 以构造函数的形式调用

this是新创建的那个对象

  1. function Fruit(name){
  2. this.name = name;
  3. }
  4. const f1 = new Fruit('apple');
  5. const f2 = new Fruit('banana');
  6. console.log(f1.name, f2.name); // apple banana

4.显示绑定

使用 call()、apply()、bind()等方法,强制绑定调用

  1. function fruit(...args){
  2. console.log(this.name, args);
  3. }
  4. var apple = {
  5. name: '苹果'
  6. }
  7. var banana = {
  8. name: '香蕉'
  9. }
  10. fruit.call(banana, 'a', 'b') //'苹果' [ 'a', 'b' ]
  11. fruit.apply(apple, ['a', 'b']) // '香蕉' [ 'a', 'b' ]
  1. function fruit(){
  2. console.log(this.name);
  3. }
  4. var apple = {
  5. name: '苹果'
  6. }
  7. fruit = fruit.bind(apple);
  8. fruit(); // 苹果

优先级

new 绑定 -> 显示绑定 -> 隐式绑定 -> 默认绑定

箭头函数

箭头函数没有单独的 this 值,导致内部的 this 就是外层代码块的 this

  1. const obj = {
  2. x: 1,
  3. hello: function(){
  4. // 這邊印出來的 this 是什麼,test 的 this 就是什麼
  5. // 在宣告它的地方的 this 是什麼,test 的 this 就是什麼
  6. console.log(this)
  7. const test = () => {
  8. console.log(this.x)
  9. }
  10. test()
  11. }
  12. }
  13. obj.hello() // 1
  14. const hello = obj.hello
  15. hello() // undefined

不要在原型链上定义箭头函数,可能会造成 this 对象的错误理解

  1. function Fruit(name) {
  2. this.name = name;
  3. }
  4. Fruit.prototype.info = () => {
  5. console.log(this.name);
  6. }
  7. var name = 'Banana'
  8. const f1 = new Fruit('Apple');
  9. f1.info(); //'Banana'

箭头函数的一些特征:

  • 没有 this
  • 没有 arguments
  • 不能使用 new 进行调用,箭头函数没有[[Construct]]方法,所以不能被用作构造函数
  • 不存在 prototype 这个属性
  • 没有 super

    箭头函数 => 没有创建任何绑定。箭头函数只是没有 thisthis 的查找与常规变量的搜索方式完全相同:在外部词法环境中查找。