-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JavaScript 中的 this #66
Comments
前端面试必会 | 一文读懂 JavaScript 中的 this 关键字
JavaScript 中的 thisJavaScript 引擎在查找 Function Invocation Pattern普通的函数调用,这是我们使用较多的一种, function foo() {
console.log(this)
}
foo() // Window Method Invocation Pattern函数作为对象的方法调用,会通过 const obj = {
name: 'lxfriday',
getName(){
console.log(this.name)
}
}
obj.getName() // lxfriday Constructor Pattern通过 function Person(name){
this.name = name
}
const person = new Person('lxfriday')
console.log(person.name) // lxfriday Apply Pattern通过 掌握以上的几种函数调用形式就基本可以覆盖开发中遇到的常见问题了,下面我翻译了一篇文章,帮助你更深入的理解
如果你已经使用过一些 JavaScript 库,你一定会注意到一个特殊的关键字
在这篇文章中,我将帮助您深入了解 在深入了解之前,请确保已在系统上安装了 Node 。然后,打开命令终端并运行 node 命令。 全局环境中的 this
在全局层面中, $ node
> this === global
true 但上述情况只出现在 Node repl 环境中,如果我们在 JS 文件中跑相同的代码,我们将会得到不同的答案。 为了测试,我们创建一个 console.log(this === global); 然后通过 $ node index.js
false 出现上面情况的原因是在 JS 文件中, 函数中的 this
在函数中 在 function fat() {
console.log(this === global)
}
fat() 如果我们在 Node repl 环境执行上面的代码,将会得到 为了进一步说明这一点,让我们创建一个定义超级英雄的真实姓名和英雄姓名的简单函数。 function Hero(heroName, realName) {
this.realName = realName;
this.heroName = heroName;
}
const superman= Hero("Superman", "Clark Kent");
console.log(superman); 请注意,这个函数不是在严格模式下执行的。代码在 node 中运行将不会出现我们预期的 这背后的原因是由于该函数不是以严格模式编写的,所以 如果我们在严格模式下运行这段代码,会因为 JavaScript 不允许给 最后,以大写形式编写函数的名称意味着我们需要使用 const superman = new Hero("Superman", "Clark Kent");
console.log(superman); 再次运行 构造函数中的 this
JavaScript 没有任何特殊的构造函数。我们所能做的就是使用 进行构造函数调用时,将创建一个新对象并将其设置为函数的 在 return {
heroName: "Batman",
realName: "Bruce Wayne",
}; 如果现在运行 当 方法中的 this
当将函数作为对象的方法调用时, 在下面代码中,有一个 const hero = {
heroName: "Batman",
dialogue() {
console.log(`I am ${this.heroName}!`);
}
};
hero.dialogue(); 上面的代码非常简单,但是实际开发时有可能方法调用的接收者并不是原对象。看下面的代码: const saying = hero.dialogue();
saying(); 这里,我们把方法赋值给一个变量,然后执行这个变量指向的函数,你会发现 当我们将一个方法作为回调传递给另一个方法时,通常会发生接收器的丢失。我们可以通过添加包装函数或使用 call、apply
尽管函数的 让我们像这样重组前面的代码片段: function dialogue () {
console.log (`I am ${this.heroName}`);
}
const hero = {
heroName: 'Batman',
}; 我们需要将 dialogue.call(hero)
// or
dialogue.apply(hero) 需要注意的是,在非严格模式下,如果传递 function dialogue() {
console.log('this', this)
}
const hero = {
heroName: 'Batman',
}
console.log(dialogue.call(null)) 上述代码,在严格模式下输出 bind当我们将一个方法作为回调传递给另一个函数时,始终存在丢失该方法的预期接收者的风险,导致将
const hero = {
heroName: "Batman",
dialogue() {
console.log(`I am ${this.heroName}`);
}
};
// 1s 后打印:I am Batman
setTimeout(hero.dialogue.bind(hero), 1000); 注意:对于用 箭头函数中的 this箭头函数和普通函数有很大的不同,引用阮一峰 ES6入门第六章中的介绍:
上面四点中,第一点尤其值得注意。 让们看下面的代码: const batman = this;
const bruce = () => {
console.log(this === batman);
};
bruce(); 在这里,我们将 那箭头函数中的 箭头函数可以帮助我们在回调中访问 const counter = {
count: 0,
increase() {
setInterval(function() {
console.log(++this.count);
}, 1000);
}
}
counter.increase(); 运行上面的代码,会打印 要使此计数器工作,可以用箭头函数重写,下面代码将会正常运行: const counter = {
count: 0,
increase () {
setInterval (() => {
console.log (++this.count);
}, 1000);
},
};
counter.increase (); 类中的 this类是所有 一个类通常包含一个 但是,在使用方法的情况下,如果该方法以普通函数的形式调用,则 我们用类重写上面的 class Hero {
constructor(heroName) {
this.heroName = heroName;
}
dialogue() {
console.log(`I am ${this.heroName}`)
}
}
const batman = new Hero("Batman");
batman.dialogue();
但是,如果我们存储对 为什么是指向 const say = batman.dialogue.bind(batman);
say(); 当然,我们也可以在构造函数内部绑定: class Hero {
constructor(heroName) {
this.heroName = heroName
this.dialogue = this.dialogue.bind(this)
}
dialogue() {
console.log(`I am ${this.heroName}`)
}
} 加餐:手写 call、apply、bind
Function.prototype.call = function(thisObj) {
thisObj = thisObj || window
const funcName = Symbol('func')
const that = this // func
thisObj[funcName] = that
const result = thisObj[funcName](...arguments)
delete thisObj[funcName]
return result
}
Function.prototype.apply = function(thisObj) {
thisObj = thisObj || window
const funcName = Symbol('func')
const that = this // func
const args = arguments[1] || []
thisObj[funcName] = that
const result = thisObj[funcName](...[thisObj, ...args])
delete thisObj[funcName]
return result
}
Function.prototype.bind = function(thisObj) {
thisObj = thisObj || window
const that = this // func
const outerArgs = [...arguments].slice(1)
return function(...innerArgs) {
return that.apply(thisObj, outerArgs.concat(innerArgs))
}
} 最后往期精彩:
关注公众号可以看更多哦。 感谢阅读,欢迎关注我的公众号 云影 sky,带你解读前端技术,掌握最本质的技能。关注公众号可以拉你进讨论群,有任何问题都会回复。 |
形成文章:
ref
JavaScript 知识树 #65
The text was updated successfully, but these errors were encountered: