(译文)掌握JavaScript基础--理解this关键字的新思路
普通函数
下面这种就是普通函数
function add(x, y) {
return x + y;
}
每个普通函数被调用的时候,都相当于有一个this参数传进来。
内部函数this不会是外部函数传入的this,相当于和外部的this隔离开了。
function outer() {
function inner() {
console.log(this); // window
}
console.log(this); // 'outer'
inner();
}
outer.call('outer');
相当于:
function outer(_this) {
function inner(_this) {
console.log(_this); // undefined
}
console.log(_this); // 'outer'
inner(undefined);
}
outer('outer');
箭头函数
const add = (x, y) => {
return x + y;
};
如果你用箭头函数,内部函数的this和外部是一致的:
function outer() {
const inner = () => {
console.log(this); // 'outer'
};
console.log(this); // 'outer'
inner();
}
outer.call('outer');
箭头函数的this不会被call方法影响,它总是和箭头函数所在的位置有关:
它所在的位置(也就是作用域)的this指向谁,箭头函数里面的this就指向谁。
function ordinary() {
const arrow = () => this;
console.log(arrow.call('goodbye')); // 'hello'
}
ordinary.call('hello');
普通函数作为方法
如果一个函数赋值给了属性,就变成了方法:
const obj = {
prop: function () {}
};
调用方法的方式是:
obj.prop(x, y)
相当于:
obj.prop.call(obj, x, y)
陷阱
1 回调函数里面用this
回调里面执行(A),你发现logStatus访问不了。这个是因为this被阻隔了。
performCleanup() {
cleanupAsync()
.then(function () {
this.logStatus('Done'); // (A)
});
}
你应该采用箭头函数:
performCleanup() {
cleanupAsync()
.then(() => {
this.logStatus('Done');
});
}
2 map方法里面用this
同理,this也是访问不了company和name的
prefixNames(names) {
return names.map(function (name) {
return this.company + ': ' + name; // (A)
});
}
采用箭头函数:
// Inside a class or an object literal:
prefixNames(names) {
return names.map(
name => this.company + ': ' + name);
}
3 用函数作为回调
class UiComponent {
constructor(name) {
this.name = name;
const button = document.getElementById('myButton');
button.addEventListener('click', this.handleClick); // (A)
}
handleClick() {
console.log('Clicked '+this.name); // (B)
}
}
改为:
class UiComponent {
constructor(name) {
this.name = name;
const button = document.getElementById('myButton');
button.addEventListener(
'click', this.handleClick.bind(this)); // (A)
}
handleClick() {
console.log('Clicked '+this.name);
}
}
bind函数能让普通的函数调用无法修改this:
function returnThis() {
return this;
}
const bound = returnThis.bind('hello');
bound(); // 'hello'
bound.call(undefined); // 'hello'
保持正确的做法
1 用ESlint的rules: no-invalid-this
避免普通函数内部有this,一般在方法内使用this或者箭头函数内使用
2 不要把this当做参数
因为这样你就不能用箭头函数了
beforeEach(function () {
this.addMatchers({ // access API object
toBeInRange: function (start, end) {
···
}
});
});
可以很容易被改写:
beforeEach(api => {
api.addMatchers({
toBeInRange(start, end) {
···
}
});
});
原文链接:http://2ality.com/2017/12/alternate-this.html
作者知乎/公众号:前端疯 (一群热爱前端的一线程序员维护,想要用前端改变世界。)

(译文)掌握JavaScript基础--理解this关键字的新思路的更多相关文章
- JavaScript闭包理解【关键字:普通函数、闭包、解决获取元素标签索引】
以前总觉得闭包很抽象,很难理解,所以百度一下"闭包"概览,百度的解释是:“闭包是指可以包含自由(未绑定到特定对象)变量的代码块:这些变量不是在这个代码块内或者任何全局上下文中定义的 ...
- JavaScript基础——理解变量作用域
一旦你开始在JavaScript应用程序中添加条件.函数和循环,就需要理解变量作用域.变量作用域规定了如何确定正在执行的代码行上的一个特定变量名的值. JavaScript允许你既定义全局版本又定义局 ...
- JavaScript闭包理解【关键字:普通函数、变量访问作用域、闭包、解决获取元素标签索引】
一.闭包(Closure)模糊概述 之前总觉得闭包(Closure)很抽象而且难理解,百度一下"闭包"名词,百度的解释是:“闭包是指可以包含自由(未绑定到特定对象)变量的代 ...
- (译文)JavaScript基础——JavaScript中的深拷贝
在JavaScript中如何拷贝一个对象? 通过引用调用 function mutate(obj) { obj.a = true; } const obj = {a: false}; mutate(o ...
- javascript基础 之 保留关键字
1,保留关键字 意思是:特定的字符串要么是已经有指代了要么是未来将要有指代,所以取名字不要用保留关键字里的字符串 js保留关键字 abstract arguments boolean break by ...
- JavaScript基础理解及技巧(入门)
1.java和JavaScript的区别: (1)js只需要解释就可以执行了,而java需要先编译成字节码文.JavaScript的运行只需要浏览器的支持,而java的运行需要JVM(java虚拟机) ...
- 转载 深入理解JavaScript中的this关键字
转载原地址: http://www.cnblogs.com/rainman/archive/2009/05/03/1448392.html 深入理解JavaScript中的this关键字 1. 一 ...
- 如何理解JavaScript中的this关键字
前言 王福朋老师的 JavaScript原型和闭包系列 文章看了不下三遍了,最为一个初学者,每次看的时候都会有一种 "大彻大悟" 的感觉,而看完之后却总是一脸懵逼.原型与闭包 可以 ...
- 理解javascript中的with关键字
说起js中的with关键字,很多小伙伴们的第一印象可能就是with关键字的作用在于改变作用域,然后最关键的一点是不推荐使用with关键字.听到不推荐with关键字后,我们很多人都会忽略掉with关键字 ...
随机推荐
- 如何创建Filter的属性页
本篇文档我们将要讲述如何给一个filter创建一个属性页,通过CBasePropertyPage基类.这篇文档的实例代码演 示了创建属性页的步骤,这里我们假设我们要创建属性页的视频filter支持饱和 ...
- Centos运行Mysql因为内存不足进程被杀
今天刚刚申请了一个新的域名,在申请完域名刚准备绑定给小伙伴分享注册新域名的喜悦时,刚把网站发到我们小伙伴们的讨论群里,却发现访问不了了,提示,数据库连接失败! 真的时一个尴尬..... 所有人都 ...
- java第一个程序——Hello World
Hello World 如果没有下载jdk以及配置环境变量的萌新请自行百度,教程非常的详细(参考:https://jingyan.baidu.com/article/6dad5075d1dc40a12 ...
- Project入门学习
Microsoft Office Project制定项目计划时,针对每项任务是可以分配具体的资源的,比如由某个人完成某项任务,或者把某项设备分配到某项任务,这样便于项目的管理和人员.设备的安排及有效利 ...
- jtyhon 介绍
Jython是Python的纯Java实现.她无缝地结合了Java类与Python,使用户能以Python语言的语法编写在Java虚拟机上运行的 软件.它的特点有:与相似的Java程序相比,Jytho ...
- 元素定位-----Selenium快速入门(二)
一.eclipse设置 工欲善其事必先利其器,在说元素定位之前,先来设置下eclipse. 首先放大一下字体,点击windows-preferences 其次,eclipse对于java的智能提示默认 ...
- 【BZOJ4552】排序(线段树,二分答案)
[BZOJ4552]排序(线段树,二分答案) 题面 BZOJ 题解 好神的题啊 直接排序我们做不到 怎么维护? 考虑一下,如果我们随便假设一个答案 怎么检验它是否成立? 把这个数设成\(1\),其他的 ...
- zjoi网络
map加LCT水一下就过了 # include <stdio.h> # include <stdlib.h> # include <iostream> # incl ...
- SFTP环境搭建及客户代码调用公共方法封装
一.背景 在开发应用软件的过程中,广泛使用FTP在各子系统间传送文本数据.但FTP存在安全问题,开放到外网存在安全漏洞,容易被攻击.替换方案是使用SFTP,SFTP提供更高的安全性,当然传输的效率也会 ...
- c#抽取pdf文档标题(1)
首先看看我的项目结构: 从上面的结果图中,我们可以看出,主要用了两个库:itextsharp.dll 和 pdfbox-1.8.9.dll,dll文件夹存放引用的库,handles文件夹存放抽取的处理 ...