共计 4573 个字符,预计需要花费 12 分钟才能阅读完成。
每个 JavaScript 程序猿,包含我本人,都始终在致力理解 this
关键字在代码中的真正身份。
我设计了一个通用算法,能够帮你在任何状况下确定 this
关键字的值。尽管我尽可能的使算法容易看懂,但还是倡议你多看几遍并了解相干术语。
另外还用了几个例子展现怎么用这个算法一步一步的对 this
进行评估,最初你本人亲自试一试。
1. this 算法
把算法定义为 ThisValueOfFunction(func, invocationType)
,返回值为在以 invocationtype
形式调用函数 func
时的 this
值:
ThisValueOfFunction(func, invocationType):
-
如果
func
是一个 箭头函数,那么- 如果
func
是在 最里面的作用域 中定义的,那么返回globalObject
-
否则
SuffeFunc
是Func
的 内部函数- 返回
ThisValueOfFunction(outerFunc, outerInvocationType)
- 如果
-
如果
func
是originFunc
函数的 绑定函数,那么thisArg
是Func = OriginFunc.bind(thisarg)
的参数- 返回
thisArg
-
如果
func
是someclass
类 中的constructor()
办法,那么instance
是instance = new SomeClass()
的实例- 返回
instance
-
如果
func
是一个 惯例函数,那么-
如果
invocationtype
是 作为构造函数,那么newObject
是新结构的对象newObject = new func()
- 返回
newObject
-
如果
invocationtype
是间接调用 的,那么thisArg
是func.call(thisArg)
或func.apply(thisArg)
的参数- 返回
thisArg
-
如果
invocationtype
是 办法,那么object
是在object.func()
上调用func
的对象- 返回
object
-
如果
invocationtype
是 惯例的,那么- 如果启用了 严格的模式,那么返回
undefined
- 否则返回
globalObject
- 如果启用了 严格的模式,那么返回
-
1.1 算法中应用的术语
这个算法应用了大量的 JavaScript 术语。如果你不相熟某些货色,先看上面的解释。
-
箭头函数
箭头函数是应用粗箭头语法
=>
定义的函数。箭头函数示例:const sum = (number1, number2) => {return number1 + number2;}
-
绑定函数
绑定函数是通过在函数上调用办法
myFunc.bind(thisArg, arg1, ..., argN)
创立的函数。绑定函数的示例:function originalFunction() {// ...} const boundFunction = originalFunction.bind({prop: 'Value'});
-
惯例函数
惯例函数是用
function
关键字或在对象上定义的简略 JavaScript 函数。惯例函数的示例:function regularFunction(who) {return `Hello, ${who}!`; } const object = {anotherRegularFunction(who) {return `Good bye, ${who}!` } };
-
constructor()
constructor() 是
class
外部的一种非凡办法,用于初始化类实例。class SomeClass() {constructor(prop) {this.prop = prop;} }
-
最内部的作用域
最内部的作用域是没有内部作用域的最顶级作用域。
// 最内部的作用域 let a = 1; function someFunction() {// someFunction() 的作用域 // 这里不是最内部的作用域 let b = 1; }
-
内部函数
内部函数在其作用域内蕴含另一个函数。// outerFunction() 是 myFunction() 的内部函数 function outerFunction() {function myFunction() {//...} }
- 全局对象
全局对象是在全局作用域内始终存在的对象。
window
是浏览器环境中的全局对象,在 Node 环境中是global
。 -
调用
函数的调用只是应用一些参数来调用该函数。function sum(number1, number2) {return number1 + number2;} sum(1, 3); // 调用 sum.call({}, 3, 4); // 调用 sum.apply({}, 5, 9); // 调用 const obj = {method() {return 'Some method';} }; obj.method(); // 调用 class SomeClass {constructor(prop) {this.prop = prop;} } const instance = new SomeClass('Value'); // 调用
-
结构函数调用
应用new
关键字调用函数或类时,将产生结构函数调用。function MyCat(name) {this.name = name;} const fluffy = new MyCat('Fluffy'); // 结构函数调用 class MyDog {constructor(name) {this.name = name;} } const rex = new MyDog('Rex'); // 结构函数调用
-
间接调用
应用func.call(thisArg, ...)
或func.apply(thisArg, ...)
办法调用函数时,会产生间接调用。function sum(number1, number2) {return number1 + number2;} sum.call({}, 1, 2); // 间接调用 sum.apply({}, 3, 5); // 间接调用
-
办法调用
当在属性拜访器表达式object.method()
中调用函数时,将产生办法调用。const object = {greeting(who) {return `Hello, ${who}!` } }; object.greeting('World'); // 办法调用 object['greeting']('World'); // 办法调用
-
惯例调用
只用函数参数变量调用func(...)
时,会产生惯例调用。function sum(number1, number2) {return number1 + number2;} sum(1, 4); // 惯例调用
- 严格模式
严格模式是对运行 JavaScript 代码有非凡限度的一种非凡模式。通过在脚本的结尾或函数作用域的顶部增加use strict
指令来启用严格模式。
2. 例子
例 1
const myFunc = () => {console.log(this); // logs `window`};
myFunc();
ThisValueOfFunction(myFunc,“惯例的”)
myfunc
是箭头函数:从而在算法中匹配状况 1。同时 myFunc
在最里面的作用域内定义,匹配状况 1.1。
算法 1.1 中返回 globalObject
意思是 myFunc
中的 this
值为全局对象 window
(在浏览器环境中)。
例 2
const object = {method() {console.log(this); // logs {method() {...} } }
};
object.method();
ThisValueOfFunction(object.method,“作为办法调用”)
method()
同时是 object
的属性,是惯例函数。与算法的状况 4 匹配。
object.method()
是一种办法调用,因为是属性拜访的,送一因而与 4.3 匹配。
而后,依据 4.3,method()
办法中的 this
等于办法的拥有者 (object.method()
) — object
。
例 3
function MyCat(name) {
this.name = name;
const getName = () => {console.log(this); // logs {name: 'Fluffy', getName() {...} } return this.name;
}
this.getName = getName;
}
const fluffy = new MyCat('Fluffy');
fluffy.getName();
ThisValueOfFunction(getName,“作为办法调用”)
getName()
是一个箭头函数,所以合乎算法的状况 1;因为 mycat
是 getName()
的内部函数,而后与 1.2 匹配。
分支 1.2.2:this
在 getName()
箭头函数外部的值等于内部函数的值 MyCat
。
所以让咱们在 MyCat
函数上运行算法 ThisValueOfFunction(MyCat, "做为构造函数")
。
ThisValueOfFunction(MyCat,“作为构造函数”)
MyCat
是惯例函数,所以跳转到算法的分支 4。
因为 MyCat
做为结构函数调用 new MyCat('Fluffy')
,合乎分支 4.1。最初依据 4.1.1 和 4.1.2,this
在 MyCat
中等于结构的对象:fluffy
。
而后,返回箭头函数后合乎 1.2.2,在 getname()
中的 this
等于 mycat
的 this
,最终后果为 fluffy
。
3. 练习
要了解这个算法,最好本人亲自试试。上面是 3 个练习。
练习 1
const myRegularFunc = function() {console.log(this); // logs ???};
myRegularFunc();
如何确定 myRegularFunc()
中的 this
值?写出你的判断步骤。
练习 2
class MyCat {constructor(name) {
this.name = name;
console.log(this); // logs ??? }
}
const myCat = new MyCat('Lucy');
如何确定 new MyCat('Lucy')
中的 this
值?写出你的判断步骤。
练习 3
const object = {
name: 'Batman',
getName() {const arrow = () => {console.log(this); // logs ??? return this.name;
};
return arrow();};
}
object.getName();
如何确定 arrow()
中的 this
值?写出你的判断步骤。
本文首发微信公众号:前端先锋
欢送扫描二维码关注公众号,每天都给你推送陈腐的前端技术文章
欢送持续浏览本专栏其它高赞文章:
- 深刻了解 Shadow DOM v1
- 一步步教你用 WebVR 实现虚拟现实游戏
- 13 个帮你进步开发效率的古代 CSS 框架
- 疾速上手 BootstrapVue
- JavaScript 引擎是如何工作的?从调用栈到 Promise 你须要晓得的所有
- WebSocket 实战:在 Node 和 React 之间进行实时通信
- 对于 Git 的 20 个面试题
- 深刻解析 Node.js 的 console.log
- Node.js 到底是什么?
- 30 分钟用 Node.js 构建一个 API 服务器
- Javascript 的对象拷贝
- 程序员 30 岁前月薪达不到 30K,该何去何从
- 14 个最好的 JavaScript 数据可视化库
- 8 个给前端的顶级 VS Code 扩大插件
- Node.js 多线程齐全指南
- 把 HTML 转成 PDF 的 4 个计划及实现
- 更多文章 …