this详解以及相关7道面试题

前言

在看面经的时候,发现自己对this的指向依然有些模糊。看了很多this相关文章,打算写一篇文章梳理this相关知识,并用一些常见的面试题加强理解,供复习巩固使用。

如果觉得文章有歧义,请大佬指出,避免误导更多的人!!


正文

this

JavaScript 语言之中,一切皆对象,运行环境也是对象。函数都是在某个对象之中运行,this就是函数运行时所在的对象(环境)

this的为什么会出现? 因为函数可以在不同的运行环境执行,this的出现就是为了在函数内部获得(函数)当前的运行环境

JavaScript 支持运行环境动态切换,也就是说this的指向是动态的,没有办法事先确定到底指向哪个对象。这就需要我们额外的注意函数的运行环境。

先来举个例子(来自阮一峰前辈的文章),虽然都在执行foo。但是执行环境并不一样。

  • 对于obj.foo()来说,foo运行在obj环境,所以this指向obj;
  • 对于foo()来说,foo运行在全局环境,所以this指向全局环境。
var obj = {
    
    
  foo: function () {
    
     console.log(this.bar) },
  bar: 1
};

var foo = obj.foo;
var bar = 2;

obj.foo() // 1
foo() // 2

如果想更深入的了解该问题,就必须了解内存的数据结构,以下图片内容来自阮一峰的this原理

var obj = {
    
     foo: function () {
    
    } };

对于上面的代码,变量obj是一个地址。如果要读取obj.foo,要先从obj拿到内存地址,然后再从该地址读出原始的对象,返回它的foo属性。

原始的对象以字典结构保存,每一个属性名都对应一个属性描述对象。foo属性的值保存在属性描述对象的value属性里面。函数单独保存在内存中,然后再将函数的地址赋值给foo属性的value属性。
在这里插入图片描述
所以,函数是一个单独的值,所以它可以在不同的环境(上下文)执行,且JavaScript 允许在函数体内部,引用当前环境的其他变量。


使用环境

全局环境

全局环境使用this,它指的就是顶层对象window。不管是不是在函数内部,只要是在全局环境下运行,this就是指顶层对象window。

console.log(this === window); // true
function f() {
    
    
    console.log(this === window); //true
}
f() // true

如果使用了严格模式"use strict";,则其为undefined

function f(){
    
    
     "use strict";
     console.log(this);
 }
 f() //undefined

构造函数

构造函数中的this,指的是实例对象。

 var Obj = function (p) {
    
    
      this.p = p; 
      console.log(this);
  };
  var o = new Obj('Hello World!');
  console.log(o.p); // "Hello World!"

在这里插入图片描述

对象

如果对象的方法里面包含this,this的指向就是方法运行时所在的对象。 该方法赋值给另一个对象,就会改变this的指向。如下面这个例子

var a = 20; 
var obj = {
    
    
    a: 10,
    getA: function () {
    
    
        return this.a;
        }
}
console.log(obj.getA());    //10
var test = obj.getA;
console.log(test());        //20   独立调用test

注意!!!下面这种用法,会改变this的指向obj.foo就是一个值。这个值真正调用的时候,运行环境已经不是obj了,而是全局环境,所以this不再指向obj。

var obj ={
    
    
  foo: function () {
    
    
    console.log(this);
  }
};
(obj.foo = obj.foo)() // window

此外,如果this所在的方法不在对象的第一层,这时this只是指向当前一层的对象,而不会继承更上面的层。如下,a.b.m方法在a对象的第二层,该方法内部的this不是指向a,而是指向a.b

var a = {
    
    
  p: 'Hello',
  b: {
    
    
  m: function() {
    
    
          console.log(this.p);
      }
  }
  };

  a.b.m() // undefined

显示绑定

可查看该文章:

前端面试高频题——手撕call()、apply()和bind()函数代码,了解函数this的默认绑定、隐式绑定、显示绑定

相关面试题

1

var m = 10;
function fn() {
    
    
    return this.m + 1;
}
var obj = {
    
    
    m: 5,
    test1: function() {
    
    
        return fn();
    }
};
obj.test2 = fn;
 
console.log(obj.test1(), fn(), obj.test2()) // 11 11 6

如果把var 变成 let答案就是:NaN NaN 6。前两个的this.m为undefined,因为用let声明的m,属于script的作用域,而不是windows身上的属性。
在这里插入图片描述

2

var obj = {
    
       
    a: 10,
    b: this.a + 10, //这里的this指向window(全局),a为undefined  ==>  undefined + 20 = NaN
    fn: function () {
    
    
        return this.a;
    }
}
console.log(obj.b);        //NaN
console.log(obj.fn());    //10

3

var a = 5;
 function fn1(){
    
    
     var a = 6;
     console.log(a);        //6
     console.log(this.a);   //5
 }  
 function fn2(fn) {
    
    
     var a = 7;
     fn();
 } 
 var obj = {
    
    
         a: 8,
         getA: fn1
     }  
 fn2(obj.getA); 

4

// 构造函数 
 function Person(name, age) {
    
    
     this.name = name;
     this.age = age;
     console.log(this); //Person实例对象
 }   
 Person();           //window
 Person.prototype.getName = function () {
    
    
     console.log(this);    //Person实例对象
 }; 
 var p1 = new Person("test", 18);
 p1.getName();

5

 var obj = {
    
    
     foo: "test",
     fn: function(){
    
    
         var mine = this;
         console.log(this.foo);       //test
         console.log(mine.foo);       //test
         
         (function(){
    
    
             console.log(this); // window
             console.log(this.foo);    //undefined
             console.log(mine.foo);    //test
         })();  
     } 
 };
 obj.fn();

6

function test(arg) {
    
    
     this.x = arg;
     return this;
 } 
 var x = test(5);     //此时 x = window, y = undefined
 var y = test(6);     //此时 x = 6,  y = window 
 console.log(x.x);     //undefined,   6.x是undefined
 console.log(y.x);     //6     实际上是window.x 也就是6

7

var obj = {
    
    
    data: [1,2,3,4,5],
    data2: [1,2,3,4,5],
    fn: function () {
    
    
       console.log("--test--");
       console.log(this);   //Object
       return this.data.map(function (item) {
    
    
             console.log(this);     //window
             return item * 2;
        }); 
    },
    fn2: function () {
    
    
       console.log("---test2---");
       console.log(this);     //Object
       return this.data2.map(item=>{
    
    
           console.log(this);   //Object
           return item * 2; 
       });
    }
 };  
 obj.fn();
 obj.fn2();

如果觉得本篇文章有用,记得点赞、收藏!!

猜你喜欢

转载自blog.csdn.net/qq_45890970/article/details/123734078
今日推荐