9. 关於 this 的 5 题练习

这篇只包含我自己不熟悉的题型,建议有看到文章的人自己做做看题目

题目来自 六角学院观念测验:JavaScript 热门面试题
(目前题型是公开的,如果之後题目表单关闭,这篇文章会删除。)

觉得自己对this没概念的人可以先看这篇:浅谈 JavaScript 头号难题 this:绝对不完整,但保证好懂 - Huli

然後题目都是在browser执行!!用node执行大部分答案都会不一样。

-----正文开始-----

  1. 请问 this 将会出现什麽答案?
function callName() {
    console.log(this.name); 
}
var auntie = {
    name: '漂亮阿姨',
    callName: callName,
    watch: {
        name: 'Magic Watch',
        callName: callName,
    }
}

var callName1 = auntie;                 
var callName2 = auntie.watch;           
var callName3 = callName1.callName();   
var callName4 = callName2.callName;     

 callName3;
 callName4;

题解

  • callName3 = callName1.callName() = auntie.callName()
    这里的callName()函式宣告(Function Declaration) 的this,而函式宣告的this指向执行呼叫的物件。
    这里执行呼叫的是auntie,所以 this = auntie。
    this.name = auntie.name : 漂亮阿姨

  • callName4 = callName2.callName,要注意的是: 这里的callName并没有呼叫"()"。 所以这里的callName会回传 整个callName的函式宣告 回来。

Ans. 漂亮阿姨 / function callName()

自主练习
如果是执行呼叫的话,把var callName4 = callName2.callName;改成:

var callName4 = callName2.callName(); 
  • callName4 = callName2.callName() = auntie.watch.callName()
    这里的callName物件方法(object method) 的this,物件方法的this指向物件本身,这里指的物件是auntie.watch,所以auntie.watch.callName() : Magic Watch
  1. 请问 this 将会出现什麽答案?
var name = '小明';
var obj = {
    x: () => {
        name = '小王';
        console.log(this.name);
    },
    y: '2',
}

obj.x(); 


题解

  • 在browser里,var name的宣告会被放进browser的global物件 Window.name的属性,let nameconst name则不会有影响。
  • obj.x();执行了两个工作:
    1. 将变数name设为'小王': 这里找到的name就是已经被设为'小明'的Window.name,所以现在的 Window.name 会从'小明'变成'小王'。
    2. console.log(this.name); : 这里的this是**箭头函式(Arrow functions)**的this,因为箭头函式不拥有this,因此这里的this是指window
      因此,this.name = Window.name = '小王'。

Ans. 小王
(在node.js里执行,this会是Global,而this.name会变成undefined。)

  1. 请问 this 将会出现什麽答案?
var name = '小明';
var obj = {
    x: {
        name: '小虎',
        myname: function() {
            console.log(this.name);
            setTimeout(function() {  
                console.log(this.name);
            }, 500)
        }
    },
    y: '2',
    name: '小王',
}

var a = obj.x.myname(); 
a;
// in Browser: 小虎/ 小明
// node : 小虎/ undefined

题解

  • a = obj.x.myname();
    1. 这里的第一个this.name是函式宣告的this,会指向呼叫函式的物件obj.x。所以this.name = obj.x.name = '小虎'。
      2. 第二个this.name被放在setTimeout里面,由於setTimeout(),setInterval()等非同步呼叫的程序码,运行在与其他函式不同的执行环境,抓取不到物件,所以this会指向window。所以 this.name = window.name = '小明'。

Ans. 小虎 / 小明

4.请问 this 将会出现什麽答案?

function callName(name){
    console.log(this.name, name); 
}
var name = '全域阿婆';
var auntie = {
    name: '漂亮阿姨',
}

callName(undefined, '小明');        
callName.call(auntie, '小明');      
  • console.log(this.name, name);是函式宣告的this,this会指向呼叫函式的物件。
    1. this.name: 这里执行callName(undefined, '小明');的方式是 simple call,this指向的物件是window,所以 【this.name = window.name = '全域阿婆'。】
    2. name: function callName(name)里的name会参考到传入的参数,在这里是 undefined
      至於参数的'小明'是多余的参数,JS只是不会在有过多参数的时候报错,但是会忽略他。
  • callName.call(auntie, '小明'); call()的第一个参数是指定呼叫函式的对象,第二个以後的参数会是预计传入函式的参数。所以这个函式也可以看成 auntie.callName('小明')
    所以这里可以很明显的看出来,这里的this = auntie
    1. this.name = auntie.name = '漂亮阿姨'
    2. name = undefined

Ans. 全域阿婆 / undefined,漂亮阿姨 / 小明

  1. 请问 this 将会出现什麽答案?
var name = '全域';
var auntie = {
    name: '漂亮阿姨',
    callName: function() {
        console.log(this.name); 
    }
};
(function(){
    var a = auntie.callName;
    a();
})();

题解

  • 最大的前提还是function是函式宣告,this指向呼叫韩式的物件。
  • var a = auntie.callName这里要注意callName没有被呼叫"()",所以这里可以看成**a是一个会执行console.log(this.name)的function。**
  • a()执行的Simple call,所以a()的this指向的是window
    因此 this.name = window.name = '全域'

Ans. 全域

比较

var name = '全域';
var auntie = {
    name: '漂亮阿姨',
    callName: function() {
        console.log(this.name);  //auntie.name = "漂亮阿姨"
    }
};
(function(){
    var a = auntie.callName();
    a;
})();

相较於上面的例子, auntie.callName()代表呼叫callName的物件是auntie,所以这里的this也指向auntie。
所以当输入a;时,这里回传的会是auntie.callName()。
this.name = auntie.name = '漂亮阿姨'。

【如内文有误还请不吝告知>< 谢谢阅览至此的各位:D】

-----正文结束-----

考虑了很久要不要写this的文章,但我觉得还是做题目最容易理解。
因为都是写给我自己的,所以这篇可能对社会特别没贡献QQ。但我有尽量把专有名词写出来,即使看不懂,查起资料来应该也比较方便。


<<:  Android工程师说:只有「不当Android工程师」才是「好工程师」

>>:  DAY10 - [CSS+RWD] 合体吧!网页与小结

DAY 16 『 改用 xib 进行界面创作 』

storyboard 有三个概念是最容易混淆: xib:实际是个xml文件,xib = XML n...

2020网页切版直播班-心得

前言 今年四月离了职,开始了调光freelancer和转职计画... 这个决定已经前前後後思考了一年...

[FGL] 程序开发(2) - 4类6个交谈指令-功能选单部分

FGL程序运行时可用的画面已经可做出来了,但总不能只是拿来 DISPLAY TO 资料,应该要拿来...

day10_MacOs ARM 的软件开发之旅

Mac ARM 作为主要开发机是否可行? 对我来说,完全可以,我有在撰写的语言为 C#, JS, J...

[day-9] 认识Python的基本资料型别!

认识Python的基本资料型别吧!   每个程序语言都有各自独特的资料型别,让我们快速认识Pytho...