乐趣区

关于javascript:再也不怕面试中this的指向问题

参考

【第 1318 期】深入浅出 JavaScript 关键词 — this
https://juejin.cn/post/684490…

写这篇文章起因

因为总结面经中遇到了 this 的指向问题,这也是面试官常问的根底问题。所以独自列出来供参考学习

this 指向几点判断规定

js 的函数除了申明定义的形参之外,每个函数还承受两个附加参数:this 和 arguments。this 的值并不是由函数定义放在哪个对象外面决定,而是函数执行时由谁来唤起决定。

  1. 函数调用模式:strict 状况下,指向 undefined,否则指向全局变量
  2. 办法调用模式:指向办法所在的对象
  3. 构造函数模式调用,用 new 时,this 指向新构建的对象
  4. apply,call 明确绑定:或者 bind 绑定,this 指向被绑定的对象
  5. 箭头函数 外部的 this 就是外层代码块的this,包裹在函数中时 this 指向函数调用时所在的对象,若放在全局中则是指向全局对象 window,且不会扭转
// Q1 规定 1:如果一个函数中有 this,然而它没有被上一级的对象所调用,那么 this 指向的就是 window
var a = 1;
function print () {console.log(this.a)
}            
print()  //a=1

// Q2 规定 2:如果一个函数中有 this,这个函数有被上一级的对象所调用,那么 this 指向的就是上一级的对象。const obj = {
 a: 2,
 print: function () { console.log(this.a) }
}
obj.print();  //2
​
// Q3 
const obj = {
 a: 3,
 print: function () { console.log(this.a) }
}
obj.print()  //3  与上面的 foo()区别在于是全局环境还是 obj 环境
const foo = obj.print; 
foo()     //undefined      全局状况下调用的,没有全局变量 a

// Q3.1   如果一个函数中有 this,这个函数中蕴含多个对象,只管这个函数是被最外层的对象所调用,this 指向的也只是它上一级的对象
const obj = {
    a: 3,
    printOut:{
        a:4,
        printIn: function(){ console.log(this.a)},
    },
}
obj.printOut.printIn()    //4 
const foo = obj.printOut.printIn;  
foo()     //undefined      全局状况下调用的,没有全局变量 a
​
// Q4  Q4-Q9 参见规定 5
const obj = {
 a: 4,
 print: () => { console.log(this.a) }
}
obj.print();                 //undefined     有箭头函数,对象不形成独自的作用域,导致 `print` 箭头函数定义时的作用域就是全局作用域。​
// Q5
var a = 5
const obj = {
 a: 6,
 print: () => { console.log(this.a) }
}
obj.print.call({a: 7}); //5         理由同上
​
// Q6 
function Person () {
 this.a = 8
 this.print = function () {console.log(this.a)}
 return {a: 9} 
}
const p = new Person()  
console.log(p.a)  //9   此时 p 为构造函数返回的{a:9}
console.log(p.print())  // undefined p 是没有 print 函数的
​
// Q7 
'use strict';
var a = 1;
​
function print () {console.log(this.a)
}
print()    //undefined 严格模式下,this 指向 undefined

// Q8 一般函数
function foo() {setTimeout(function() {console.log('id:', this.id);
  });
}
var id = 21;
foo.call({id: 42}); //21

//Q9 箭头函数,匿名函数定义时所在的执行环境就是 foo 函数,所以匿名函数外部的 this 执向始终会和 foo 函数的 this 执向保持一致,指向 call 的对象。为什么指向 call 的对象呢?参见 call 的用法:函数名.call(对象,arg1,arg2,...argn), 性能是调用函数,并把函数外部的 this 指向第一个参数的对象,而后将第二个及之后的是所有的参数,作为实参传给函数。function foo() {setTimeout(() => {console.log('id:', this.id);
  }, 100);
}

var id = 21;
foo.call({id: 42}); //42

function foo() {setTimeout(() => {console.log('id:', this.id);
  }, 100);
}

var id = 21;
foo(); //21(没有用 call)// Q10
var A = function(name){this.name = name;};
var B = function(){A.apply(this,arguments);
};
B.prototype.getName = function(){return this.name;};
var b=new B('sven');
console.log(b.getName() ); // 输入:  'sven'
退出移动版