默认绑定 隐式绑定(隐式丢失) 显式绑定 new 绑定 严格模式下的 this 箭头函数绑定 默认绑定 this 指向 window 例子 1:在全局环境中,this 默认绑定到 window 例子 2:函数独立调用的时候,this 默认绑定到 window 例子 3:被嵌套函数独立调用的时候,this 默认绑定到 window 例子 4:IIFE 立即执行函数实际上是函数声明后直接调用执行 相当…

  1. 默认绑定
  2. 隐式绑定(隐式丢失)
  3. 显式绑定
  4. new 绑定
  5. 严格模式下的 this
  6. 箭头函数绑定

默认绑定

this 指向 window

  1. 例子 1:在全局环境中,this 默认绑定到 window
console.log(this === window);
// 输出
// true
// 例子2:函数独立调用的时候,this默认绑定到window
  1. 例子 2:函数独立调用的时候,this 默认绑定到 window
function foo1() {
  console.log(this === window);
}
foo1();
// 输出
// true
  1. 例子 3:被嵌套函数独立调用的时候,this 默认绑定到 window
var a = 0;
var obj1 = {
  a: 2,
  foo: function() {
    function test() {
      console.log(this.a);
    }
    test();
  }
};
obj1.foo();
// 输出
// 0
  1. 例子 4:IIFE 立即执行函数实际上是函数声明后直接调用执行
var a = 0;
function foo2() {
  (function test() {
    console.log(this.a);
  })();
}
var obj = {
  a: 2,
  foo: foo2
};
obj.foo();
// 输出
// 0

相当于

var a = 0;
var obj = {
  a: 2,
  foo: function() {
    function test() {
      console.log(this.a);
    }
    test();
  }
};
obj.foo();
// 输出
// 0
  1. 例子 5:闭包下的 this
// 例子4:闭包
var a = 0;

function foo3() {
  function test() {
    console.log(this.a);
  }
  return test;
}
var obj = {
  a: 2,
  foo: foo3
};
obj.foo()();
// 输出
// 0
  1. 例子 6:如何访问嵌套函数 this 的值
var a = 0;

function foo4() {
  var that = this;

  function test() {
    console.log(that.a);
  }
  return test;
}
var obj = {
  a: 2,
  foo: foo4
};
obj.foo()();
// 输出
// 2

隐式绑定

被对象的方法调用时,this 隐式绑定到该对象

  1. 例子 1
function foo5() {
  console.log(this.a);
}
var obj1 = {
  a: 1,
  foo: foo5,
  obj2: {
    a: 2,
    foo: foo5
  }
};
obj1.foo();
obj1.obj2.foo();
// 输出
// 1
// 2
  1. 例子 2
function foo() {
  console.log(this.a);
}
var a = 2;
var o = {
  a: 3,
  foo: foo
};
var p = {
  a: 4
};
o.foo();
// 这个和 var bar = obj.foo; 隐式丢失不一样,这是把函数赋值给p.foo,属于p对象的foo函数执行
p.foo = o.foo;
p.foo();
// 输出
// 3
// 4

隐式丢失

隐式绑定的函数丢失了绑定对象,导致 this 绑定到 window

  1. 例子 1:函数别名导致隐式丢失

    把 obj.foo 赋给变量 bar,导致了隐式丢失,只是把函数赋给了 bar,bar 与 obj 无任何关系

var a = 0;
function foo6() {
  return this.a;
}
var obj = {
  a: 2,
  foo: foo6
};
console.log(obj.foo());
var bar = obj.foo;
console.log(bar());
// 输出
// 2
// 0
// 等价于
var a = 0;
var bar2 = function foo() {
  console.log(this.a);
};
bar2();
  1. 例子 2:参数传递导致隐式丢失

    obj.foo 作为参数传递给 bar3 函数,知识把 foo8 函数赋给了 fn,fn 与 obj 没有关系

var a = 0;
function foo8() {
  console.log(this.a);
}
function bar3(fn) {
  fn();
}
var obj = {
  a: 2,
  foo: foo8
};
console.log(bar3(obj.foo));
// 输出
// 0
// 等价于
var a = 0;
function bar4(fn) {
  fn();
}
bar4(function foo() {
  console.log(this.a);
});
  1. 例子 3:内置函数导致隐式丢失
var a = 0;
function foo9() {
  console.log(this.a);
}
var obj = {
  a: 2,
  foo: foo9
};
setTimeout(obj.foo, 100);
// 输出
// 0
// 等价于
var a = 0;
setTimeout(function foo() {
  console.log(this.a);
}, 100);
  1. 例子 4:间接引用导致隐式丢失

    只是将 o.foo 函数赋值给 p.foo 函数,然后立即执行,仅仅是 foo 函数的立即执行

function foo10() {
  console.log(this.a);
}
var a = 0;
var o = {
  a: 3,
  foo: foo10
};
var p = {
  a: 4
};
o.foo();
(p.foo = o.foo)();
// 输出
// 3
// 0
  1. 例子 5:其他情况丢失了 this 绑定
var a = 0;
function foo11() {
  console.log(this.a);
}
var obj4 = {
  a: 2,
  foo: foo11
};
// obj.foo和foo的内存地址不一样,所以this指向window
(obj.foo = obj4.foo)();
// 执行的是obj4.foo=bj4.foo
(false || obj4.foo)();
// 执行的是obj4.foo=bj4.foo
(1, obj4.foo)();
// 输出
// 0
// 0
// 0

显式绑定

通过 call()、apply()、bind()把对象绑定到 this 上

  1. 例子 1
var a = 0;
function foo12() {
  console.log(this.a);
}
var obj = {
  a: 2
};
foo12();
foo12.call(obj);
// 输出
// 0
// 2
  1. 例子 2:硬绑定

    在函数内部,强制 this 指向绑定的对象

var a = 0;
function foo13() {
  console.log(this.a);
}
var obj = {
  a: 2
};
var bar = function() {
  foo13.call(obj);
};
bar();
setTimeout(bar, 100);
bar.call(window);
// 输出
// 2
// 2
// 2
  1. 例子 3

    数组内置方法 map()、forEach()、filter()、some()、every()可以进行显示绑定

var a = 0;
function foo() {
  console.log(this.a);
}
var obj = {
  a: 2
};
[1].forEach(foo);
[1].forEach(foo, obj);
// 输出
// 0
// 2

new 绑定

如果函数或者方法调用之前有关键字 new,构成了构造函数,对于 this 来说,称为 new 绑定

  1. 例子 1
function fn2() {
  this.a = 2;
}
var test = new fn2();
console.log(test.a);
// 输出
// 2
  1. 例子 2
function fn3() {
  this.a = 2;
  return 1;
}
var test = new fn3();
console.log(test.a);
// 输出
// 2
  1. 例子 3
var obj = {
  a: 0
};
function fn4() {
  this.a = 2;
  return obj;
}
var test = new fn4();
console.log(test.a);
// 输出
// 0
  1. 例子 4

    new 对象的方法,this 的指向不是这个对象,而是这个构造函数

var o = {
  m: function() {
    return this;
  }
};
var obj = new o.m();
console.log(obj === o);
console.log(obj.constructor === o.m);
// 输出
// false
// true

严格模式绑定

函数的 this 值始终是指定的值

  1. 例子 1

    独立调用的函数的 this 值始终是指定 undefined

function fn5() {
  'use strict';
  console.log(this);
}
fn5();
// 输出
// undefined

箭头函数绑定

this 指向定义时所在的对象,而不是运行时所在的对象

  1. 例子 1
// 箭头函数定义时所在的对象
function foo14() {
  var id = 2;
  setTimeout(() => {
    console.log(this.id);
  }, 100);
}
foo14.call({
  id: 0
});
// 输出
// 0
// 函数运行时所在的对象
var id = 2;
function foo15() {
  setTimeout(function() {
    console.log(this.id);
  }, 100);
}
foo15.call({
  id: 0
});
// 输出
// 2
  1. 例子 2
// 箭头函数定义时所在的对象
var a = 0;
var obj5 = {
  a: 2,
  foo: () => {
    console.log(this.a);
  }
};
obj5.foo();
// 输出
// 0
// 函数运行时所在的对象
var a = 0;
var obj6 = {
  a: 2,
  foo: function() {
    console.log(this.a, 1);
  }
};
obj6.foo();
// 输出
// 2
  1. 例子 3

    箭头函数的 this 无法通过 bind,call,apply 来直接修改

function foo16() {
  return () => {
    return () => {
      return () => {
        console.log(this.a);
      };
    };
  };
}
var f = foo16.call({
  a: 0
});
var t1 = f.call({
  a: 1
})()();
var t2 = f().call({
  a: 2
})();
var t3 = f()().call({
  a: 3
});
// 输出
// 0
// 0
// 0
function foo17() {
  return function() {
    return function() {
      return function() {
        console.log(this.a);
      };
    };
  };
}
var f = foo17.call({
  a: 0
});
var t1 = f.call({
  a: 1
})()();
var t2 = f().call({
  a: 2
})();
var t3 = f()().call({
  a: 3
});
// 输出
// 0
// 0
// 0

箭头函数的特点

  1. 箭头函数不绑定 this,箭头函数的 this 相当于普通变量
  2. 箭头函数的 this 寻值行为与普通变量相同,在作用域中逐级寻找
  3. 箭头函数 this 无法通过 bind,call,apply 来直接修改
  4. 改变作用域中的 this 指向就可以改变箭头函数的 this

暂无评论