几道关于this的经典练习题的理解与分析
1.
var num = 1;
var myObject = {
num: 2,
add: function() {
this.num = 3;
(function() {
console.log(this.num);
this.num = 4;
})();
console.log(this.num);
},
sub: function() {
console.log(this.num)
}
}
myObject.add();
console.log(myObject.num);
console.log(num);
var sub = myObject.sub;
sub();
答案是:(严格模式下会报错!非严格模式下输出如下答案)
1 3
3
4
4
分析:
- 首先调用myObject.add(),函数内的this是指向myObject的,所以这里的this.num = 3实际是覆盖了myObject的num,此时add外层同级的num变成了3;接下来是自执行函数,自执行函数没有任何对象调用它则是指向全局,所以第一个console输出的是1,然后将全局的num改成了4;最后执行的this.num是输出3这个没什么难理解的了~
- myobject.num现在已经被修改成了3,因此第二个输出的是3
- 全局的num已经改成了4,因此第三个输出的是4
- sub = myObject.sub这句将myObject.sub函数赋值给sub,而实际上造成了this的丢失,这里sub()执行时this是指向全局,输出的是全局的num,即4
2.
var name = 'window'
var person1 = {
name: 'person1',
show1: function () {
console.log(this.name)
},
show2: () => console.log(this.name),
show3: function () {
return function () {
console.log(this.name)
}
},
show4: function () {
return () => console.log(this.name)
}
}
var person2 = { name: 'person2' } person1.show1()
person1.show1.call(person2) person1.show2()
person1.show2.call(person2) person1.show3()()
person1.show3().call(person2)
person1.show3.call(person2)() person1.show4()()
person1.show4().call(person2)
person1.show4.call(person2)()
答案:
person1.show1() // person1
person1.show1.call(person2) // person2 person1.show2() // window
person1.show2.call(person2) // window person1.show3()() // window
person1.show3().call(person2) // person2
person1.show3.call(person2)() // window person1.show4()() // person1
person1.show4().call(person2) // person1
person1.show4.call(person2)() // person2
我容易错的点在show2和show4,分析如下:
person1.show2() 实际是执行:()=>console.log(this.a),根据“箭头函数的this指向外层作用域”,该箭头函数外层没有函数了,即指向全局作用域
这里很有迷惑性的地方是:容易把person1这个对象的{}大括号理解为函数作用域,实际上对象并没有生成作用域!!
person1.show2.call(person2)这个根据“箭头函数直接应用bind、call、apply不起作用”,很容易可知这里this依然指向全局
person1.show4()()实际是执行了以下两步:
- 执行:function () { return ... }返回一个箭头函数
- return回来的这个箭头函数再执行
该箭头函数执行时它的外层作用域是这个show4的function,这个function的this指向person1,所以箭头函数中的this指向person1
很容易可得person1.show4().call(person2)指向person1
person1.show4.call(person2)()这个执行的时候,显式绑定将person2绑定到show4这个function上,那么依上面的分析,该箭头函数指向show4的function,所以箭头函数的this指向了person2
注意箭头函数:
箭头函数没有自己的this,它的this指向的是谁调用箭头函数的外层function,箭头函数的this就是指向谁,如果箭头函数没有外层函数,则指向window。
下面看另一道题:
var name = 'window' function Person(name) {
this.name = name;
this.show1 = function () {
console.log(this.name)
}
this.show2 = () => console.log(this.name)
this.show3 = function () {
return function () {
console.log(this.name)
}
}
this.show4 = function () {
return () => console.log(this.name)
}
} var personA = new Person('personA')
var personB = new Person('personB') personA.show1()
personA.show1.call(personB) personA.show2()
personA.show2.call(personB) personA.show3()()
personA.show3().call(personB)
personA.show3.call(personB)() personA.show4()()
personA.show4().call(personB)
personA.show4.call(personB)()
答案:
personA.show1() // personA
personA.show1.call(personB) // personB personA.show2() // personA
personA.show2.call(personB) // personA personA.show3()() // window
personA.show3().call(personB) // personB
personA.show3.call(personB)() // window personA.show4()() // personA
personA.show4().call(personB) // personA
personA.show4.call(personB)() // personB
这组例子和上一题的对比我有两个疑惑点:
- show2为什么会输出两次personA?不是指向外层作用域吗?这里外层作用域难道不是全局了?
- new绑定的优先级不是高于显示绑定吗?为什么personA.show1.call(personB)还能变成personB?
首先针对第一个疑惑点要说明的是:构造函数创建对象后其实多了一层构造函数的作用域,如图所示:
可以看到personA的scope和person1的差别:person1中的show1作用域仅仅是global,而personA中show1的函数作用域链是从构造函数产生的闭包开始的!
所以这样就很容易能知道show2的执行为什么会不同了:
personA的show2中的this指向构造函数形成的闭包函数,即Person函数,所以这里输出personA
第二个疑惑点
几道关于this的经典练习题的理解与分析的更多相关文章
- MYSQL经典练习题,熟悉DQL
MYSQL经典练习题 (本练习题可让你熟悉DQL,快速的上手DQL) 首先,先在数据库中建立基本数据库以及表项: DROP DATABASE IF EXISTS `test`; CREATE DATA ...
- 【转载】经典10道c/c++语言经典笔试题(含全部所有参考答案)
经典10道c/c++语言经典笔试题(含全部所有参考答案) 1. 下面这段代码的输出是多少(在32位机上). char *p; char *q[20]; char *m[20][20]; int (*n ...
- Python经典练习题1:一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?
Python经典练习题 网上能够搜得到的答案为: for i in range(1,85): if 168 % i == 0: j = 168 / i; if i > j and (i + j) ...
- 【视频+图文】Java基础经典练习题(一)输出2-100之间的素数,及素数个数
目录 第一题:判断2-100之间有多少个素数,并输出所有素数. 1.视频讲解: 2.思路分析: 代码讲解:以i=4为例 4.为大家准备了彩蛋: 能解决题目的代码并不是一次就可以写好的 我们需要根据我们 ...
- Python入门36道经典练习题
[程序1] 题目:有1.2.3.4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? num_list=[] cou=0 for i in range(1,5): for j in rang ...
- SQL 经典练习题
create database 练习题gouse 练习题go create table Student( Sno char(3) primary key, Sname char(8) not null ...
- python基础阶段 经典练习题 拾英札记(2)
因为编程的练习题是交互式的,在不断调试和不断渐进完善中,你会有一种成就感和快乐感,不断的修缮,不断的尝试. 其实,认知自己,和探索世界,也是这样的啊. 只要不放弃,要坚持. #7 根据列表lt,实现 ...
- MySQL经典练习题
表名和字段 –1.学生表 Student(s_id,s_name,s_birth,s_sex) –学生编号,学生姓名, 出生年月,学生性别 –2.课程表 Course(c_id,c_name,t_id ...
- SQL经典练习题50--mysql
--1.学生表 Student(Sid,Sname,Sage,Ssex)? --Sid 学生编号,Sname 学生姓名,Sage 出生年月,Ssex 学生性别 --2.课程表? Course(Cid, ...
随机推荐
- hdu多校第八场 1011 (hdu6667) Roundgod and Milk Tea 二分图匹配
题意: 有若干个班,每个班有些人要喝奶茶,也提供一些奶茶,一人喝一杯,但是自己班的人不能喝自己班的奶茶,求最多能有多少人喝上奶茶. 题解: 典型的二分图匹配问题,学生在左,奶茶在右,学生和非自己班的奶 ...
- nlp总结
中科院nlpir和海量分词(http://www.hylanda.com/)是收费的. hanlp:推荐基于CRF的模型的实现~~要看语料,很多常用词会被分错,所以需要词库支撑.目前最友好的开源工具包 ...
- [kuangbin带你飞]专题一 简单搜索 - L - Oil Deposits
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #i ...
- HtmlCleanner结合xpath用法(转载)
HtmlCleaner cleaner = new HtmlCleaner(); TagNode node = cleaner.clean(new URL("http://finance.s ...
- Eclipse代替Oracle接管Java EE
Eclipse Foundation接替Oracle成为Java EE的新东家,Oracle不再管理Java EE. 作为采用的一部分,Java EE可能会更换新名称,Oracle建议在其建议中使用J ...
- 4.1_springboot2.2任务之异步、定时、邮件任务
1.异步任务 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在Spri ...
- CentOS7中下载MySQL
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~CentOS 7中,yum默认安装的是Mariadb,但我想使用MyS ...
- 2018-10-8-Win10-使用-GHO-安装出现-UWP-软件打开闪退-应用商店无法安装软件
title author date CreateTime categories Win10 使用 GHO 安装出现 UWP 软件打开闪退 应用商店无法安装软件 lindexi 2018-10-8 18 ...
- shell 基本系统命令,关机重启,查看版本,查手册,日期,磁盘,历史命令
1. 查看系统版本及内核版本 cat /etc/issue 查看系统版本 uname -r 查看内核版本 2. 关机重启命令 关机: shutdown -h now 立即关机 shut ...
- 跟我一起使用Vue.js + Docker 部署项目
本文学习自:https://juejin.im/post/5bee5ddde51d457b8a33938c 项目环境是在ubuntu下,记得要在root目录下,不然安装vue会报错 npm insta ...