this的绑定规则及优先级

在 Javascript 中,this指向的绑定规则有以下四种:

  1. 默认绑定(非严格模式下,this指向window,严格模式下,this指向undefined)
  2. 隐式绑定(如果函数调用时,前面存在调养它的对象,那么this就会隐式绑定到这个对象上)
  3. 显示绑定(函数通过 call()、apply()、bind()调用,this指向被绑定的对象)
  4. new 绑定(函数被new 调用,this指向由new新构造出来的这个对象)

绑定规则的优先级:new 绑定 > 显式绑定 > 隐式绑定 > 默认绑定

  1. function test(){
  2. this.a = '111'
  3. }
  4. let obj = {
  5. a:'bbb',
  6. fn(){
  7. console.log(this)
  8. }
  9. }
  10. function scope(){
  11. test() // 默认绑定
  12. obj.fn() // 隐式绑定
  13. test.call(obj) // 显示绑定
  14. new test() // new绑定
  15. }
  16. const Bar = test.bind(obj);
  17. console.log(obj.a,'---',bar.a) // 'bbb --- 111'
  18. // new绑定改变了显式绑定中指定的this(obj)
  19. // 显示绑定 > new 绑定

this的几种情况

  • 全局作用域下的this指向window,严格模式下为undefined

    1. function windowScope(){
    2. console.log(this) // window or undefined
    3. }
  • 如果给元素的事件行为绑定函数,那么函数中的this指向当前被绑定的那个元素

    1. document.body.onclick = function(){
    2. console.log(this) // body
    3. }
  • 函数中的this,要看函数执行前有没有(调用者),如果有的话,调用者是谁,this就指向谁,如果没有调用者,指向window。自执行函数中的this永远指向window

    1. let fn = function() {
    2. console.log(this.name)
    3. }
    4. let obj = {name:'amy',fn};
    5. fn(); // window.name
    6. obj.fn(); //
    7. obj.name
  • 定时器中函数的this指向window

    1. setTimeout(function(){
    2. console.log(this) // window
    3. },0)
  • 构造函数中的this指向当前当前的实例

  • call、apply、bind 可以改变函数的this指向
  • 箭头函数中没有this,如果输出this,就会输出箭头函数定义时所在的作用域中的this
  • 括号表达式也有可能改变this,括号内只有一个项不会,两个或多个的话this指向window

this相关面试题

题1:

  1. var num = 10
  2. const obj = {num: 20}
  3. obj.fn = (function (num) {
  4. this.num = num * 3
  5. num++
  6. return function (n) {
  7. this.num += n
  8. num++
  9. console.log(num)
  10. }
  11. })(obj.num)
  12. var fn = obj.fn
  13. fn(5)
  14. obj.fn(10)
  15. console.log(num, obj.num)

题2:

  1. var a = {
  2. name:"zhang",
  3. sayName:function(){
  4. console.log("this.name="+this.name);
  5. }
  6. };
  7. var name = "ling";
  8. function sayName(){
  9. var sss = a.sayName;
  10. sss(); //this.name = ?
  11. a.sayName(); //this.name = ?
  12. (a.sayName)(); //this.name = ?
  13. (b = a.sayName)();//this.name = ?
  14. }
  15. sayName();

题3:

  1. var obj = {
  2. a: 1,
  3. foo: function (b) {
  4. b = b || this.a
  5. return function (c) {
  6. console.log(this.a + b + c)
  7. }
  8. }
  9. }
  10. var a = 2
  11. var obj2 = { a: 3 }
  12. obj.foo(a).call(obj2, 1)
  13. obj.foo.call(obj2)(1)

题4:

  1. var name = 'window'
  2. function Person (name) {
  3. this.name = name
  4. this.obj = {
  5. name: 'obj',
  6. foo1: function () {
  7. return function () {
  8. console.log(this.name)
  9. }
  10. },
  11. foo2: function () {
  12. return () => {
  13. console.log(this.name)
  14. }
  15. }
  16. }
  17. }
  18. var person1 = new Person('person1')
  19. var person2 = new Person('person2')
  20. person1.obj.foo1()()
  21. person1.obj.foo1.call(person2)()
  22. person1.obj.foo1().call(person2)
  23. person1.obj.foo2()()
  24. person1.obj.foo2.call(person2)()
  25. person1.obj.foo2().call(person2)