参考
【第1318期】深入浅出 JavaScript 关键词 -- this
https://juejin.cn/post/684490...
写这篇文章起因
因为总结面经中遇到了this的指向问题,这也是面试官常问的根底问题。所以独自列出来供参考学习
this指向几点判断规定
js的函数除了申明定义的形参之外,每个函数还承受两个附加参数:this和arguments。this
的值并不是由函数定义放在哪个对象外面决定,而是函数执行时由谁来唤起决定。
- 函数调用模式:strict状况下,指向undefined,否则指向全局变量
- 办法调用模式:指向办法所在的对象
- 构造函数模式调用,用
new
时,this指向新构建的对象 - apply,call明确绑定: 或者
bind
绑定,this指向被绑定的对象 - 箭头函数外部的
this
就是外层代码块的this
,包裹在函数中时this指向函数调用时所在的对象,若放在全局中则是指向全局对象window,且不会扭转
// Q1 规定1:如果一个函数中有this,然而它没有被上一级的对象所调用,那么this指向的就是windowvar 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参见规定5const obj = { a: 4, print: () => { console.log(this.a) }}obj.print(); //undefined 有箭头函数,对象不形成独自的作用域,导致`print`箭头函数定义时的作用域就是全局作用域。// Q5var a = 5const 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 }); //42function foo() { setTimeout(() => { console.log('id:', this.id); }, 100);}var id = 21;foo(); //21(没有用call)// Q10var 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'