7个关于JS中的this关键字面试题

在JS中,this 指的是函数调用的上下文。

但其实,它的行为很复杂,这也是在面试中,常常会被问到的问题。

下面来说说7个有趣的面试题。

一、可变和属性

先来看一段代码:

const object = {
        message: 'Hello, World!',

        getMessage() {
            const message = 'Hello, Earth!';
            return this.message;
        }
    };

    console.log(object.getMessage()); // 打印输出的是?

答案是“Hello,World”。

因为object.getMessage()是方法调用,所以this指向的object。

二、回答猫的名字

function Pet(name) {
        this.name = name;

        this.getName = () => this.name;
    }

    const cat = new Pet('Fluffy');

    console.log(cat.getName()); // 输出的是?

    const { getName } = cat;
    console.log(getName());     // 输出的是?

两个输出都是:“Fluffy”。

当一个函数被调用作为构造函数,该构造函数内等于所构造的对象。

this.name = name相当于构造函数中的表达式在构造name对象上创建属性。

而this.getName = () => this.name在构造函数上创建一个方法,而且它是一个箭头函数,所以this指向还是构造函数Pet。

在调用cat.getName()和getName()都是返回的this.name。

三、延时执行

const object = {
        message: 'Hello, World!',

        logMessage() {
            console.log(this.message); // 输出的是?
        }
    };

    setTimeout(object.logMessage, 1000);

在延迟1秒后,打印输出的是 undefined 。

尽管setTimeout()函数将object.logMessage()用作回调,但它仍是作为常规函数,而不是作为函数调用。

在常规函数调用中,this是作为全局对象的,可以说是指向window。

那没有声明全局message参数,所以也就说明为什么输出的是undefined。

四、功能完善

const object = {
        message: 'Hello, World!'
    };

    function logMessage() {
        console.log(this.message); // "Hello, World!"
    }

    // 怎么实现上述结果

实现的方法有三种:

const object = {
  message: 'Hello, World!'
};

function logMessage() {
  console.log(this.message); // logs 'Hello, World!'
}

// 使用call()方法
logMessage.call(object);

// 使用apply()方法
logMessage.apply(object);

// 创建约束函数
const boundLogMessage = logMessage.bind(object);
boundLogMessage();

五、问候和告别

const object = {
  who: 'World',

  greet() {
    return `Hello, ${this.who}!`;
  },

  farewell: () => {
    return `Goodbye, ${this.who}!`;
  }
};

console.log(object.greet());    // 输出的是?
console.log(object.farewell()); // 输出的是?

输出的是“Hello,World”和“Goodbye,undefined”。

调用object.greet(),方法内部的greet()的this是指向object,因为greet()是一个常规函数,所以也就能调用到object中的who。

但是farewell()是箭头函数,因此箭头函数内部的this始终指向外部,也就是object的外部。

六、棘手的长度

var length = 4;
function callback() {
  console.log(this.length); // 输出的是?
}

const object = {
  length: 5,
  method(callback) {
    callback();
  }
};

object.method(callback, 1, 2);

输出的是4.

callback()使用内部的常规函数进行调用method(),因为常规函数callback()在调用期间this等于全局对象,this.length等于window.length。

七、调用参数

var length = 4;
function callback() {
  console.log(this.length); // 输出的是?
}

const object = {
  length: 5,
  method() {
    arguments[0]();
  }
};

object.method(callback, 1, 2);

打印输出的是3.

obj.method(callback,1,2)调用时需要三个参数,callback,1和2。结果,arguments内部的特殊变量method()是具有以下结构的类似数组的对象:

{
  0: callback,
  1: 1, 
  2: 2, 
  length: 3 
}

也就是:

arguments[0]() == callback() == this指向arguments == arguments.length == 3

所以输出了3.

八,概括

看完上面的七个问题,是不是对this有了更深刻的印象和理解呢。函数的调用是执行构成函数主体的代码,或者只是调用该函数。

 

原文地址:https://www.cnblogs.com/liao123/p/14733107.html