-
Notifications
You must be signed in to change notification settings - Fork 22
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
箭头函数中this的用法 #11
Comments
var obj = {
field: 'hello',
getField:()=>{
console.log(this)
}
}
obj.getField(); 这个案例中this在node环境中是"{}"空对象,严格模式下也是空对象,这个该怎么理解? |
var obj = {
field: 'hello',
getField:()=>{
console.log(this)
}
}
obj.getField(); 这个例子的this在node下的话,就是global对象。我试过了,并没有什么问题。 我同时也尝试了
也是可以有值的 我的node的版本是6.0.0,不知道你的是什么? |
我的node版本是6.3.0 |
@preservance717 hello,我尝试了你的版本,依旧没发现有这个问题。 |
我是在Webstorm里直接运行的 |
@preservance717 原来你的案例代码是写在文件里面的,我是在命令行写的。 node下的话,因为是定义时决定的,所以文件里的这个作用域是exports或者说是module.exports。 你试下 当然,在浏览器环境的话,这个this还是window对象 |
我没有懂你的意思 |
@preservance717 就是你那段代码是写在js文件里面的,用你的截图说就是demo05.js这个文件,这跟写在命令行是不一样的 在node.js的环境下面,这个案例下的this,便是exports或者说就是module.exports,因为exports就是module.exports的引用。 你试试下这段代码便知道了 exports.field = 'test123'
var obj = {
field: 'hello',
getField:()=>{
// 这里的this就是exports对象
console.log(this)
}
}
obj.getField(); |
在node中没有写exports的话,this指的就是空对象 |
你是在vim中写代码吗? |
@preservance717 这个空对象就是exports 因为你不写exports的话,exports默认就是指向module.exports的,而module.exports就是个空对象。 因为你并没有导出任何东西 我一般用vscode的 |
原来是这样,一直疑惑为什么是空对象呢 |
那你是怎么在命令行中写的 |
奥奥,知道了。 |
想问下关于闭包的问题。这里面如果将var换成let,输出数字1~5,每秒一次,每次一个。但是var的话就是每秒一次的频率输出5次6。这是为什么呢? for(var i=1; i<=5; i++){ 发件人: Wayne Zheng notifications@github.com 直接把那段代码拷贝到node repl环境下运行 [image]https://cloud.githubusercontent.com/assets/7201693/19184014/a0785bdc-8cad-11e6-9d45-9feec3d44b78.png ― |
@zhengweikeng 看语法特性let和var的区别 |
{ 我发现我的编译结果是这样的 这是为什么 { this本身就是undefined了... |
@lumixraku 您的编译结果是什么?能不能贴出完整的代码 |
babel后得到的结果是
所以babel 后运行会报错 但是在node里直接运行第一段代码得到undefined |
@lumixraku 要看你的 babel版本,preset-2016以后的才会编译为 undefined,让代码执行时直接报错,减少错误。 定义对象方法时不推荐使用 a:()=>{}的方式,a()=>{}可以接受 |
var obj = { 这里例子没看懂。箭头函数里面的this继承上层作用域的this,难道getField的上层作用域不是obj这个对象吗?那箭头函数里面的this应该就是obj对象呀 |
@zhengweikeng ,我是这么理解的,this 在普通函数中是指向运行此函数的对象,那么在对象中呢,这个 this 是指向全局的,可以看这个例子:
上例中,输出结果是 100,证明 counter 中的 this 指向 global。同理,如果我在 counter 中定义一个箭头函数,箭头函数中的 this 也是指向 global 的:
但是,如果这个箭头函数是定义在一个对象的一个普通方法中,那又不一样的,比如:
inc() 和 inc() 中的箭头函数的 this 都指向 counter 这个对象。因为箭头函数往外找 this 的时候,首先会找到 inc() 这个普通函数中的 this,而这个 this 指向 counter 对象。 |
var obj = {
个人理解欢迎指正 |
学习javascript的人,一般来说会遇到两道坎,其中一道是原型链,另一道可能就是this问题了。js的函数不断变化的this经常让人无法摸不着头脑,很多时候我们会使用bind、call、apply来强制指定函数的this。
本文假设你已经掌握了js中的this问题了,如果你不懂,可以访问如下链接,了解下js中的this问题
图解javascript this指向什么?
词法作用域
Arrow Function中的this机制和一般的函数是不一样的。
本质来说Arrow Function并没有自己的this,它的this是派生而来的,根据“词法作用域”派生而来。
因此Arrow Function中的this是遵守“词法作用域”的
什么是词法作用域?
一般来说,作用域有两种常见的模型,一种叫做词法作用域(Lexical Scope),一种叫做动态作用域(Dynamic Scope)。而javascript采取的便是词法作用域
简单来说,所谓的词法作用域就是一个变量的作用在定义的时候就已经被定义好,当在本作用域中找不到变量,就会一直向父作用域中查找,直到找到为止。
说到这一点,我相信大家都明白了,不明白?上个例子
因为在innerFn中已经定义了b所以,因此在查找b时便不会去使用父作用域中的b了。
Arrow Function中的this便遵循了这个含义
Arrow Function中的this
先来看一个案例
最终我们会发现,两个内部函数的this都是window,而且this.name都是hello。
好像没什么区别。其实两个函数的this的产生流程是不一样的。
fn的this是在运行时产生的,由于我们是直接调用fn(),所以其this就是指向window。如果将其调用改成
这时this就是obj对象,name是haha。这个符合我们对一般函数this的理解。
接下来看看Arrow Function中的this。它是怎么产生的呢,首先根据“词法作用域”,由于它本身没有this,于是便向上查找this,于是发现taskA是有this的,于是便直接继承了taskA的作用域。
那taskA的this又是什么?很简单,taskA是一个普通的函数,普通函数的this是在运行时决定的,由于我们是直接调用taskA的,即taskA(),所以其this便是window。
这下我们便明白了,arrow_fn中的this是window的原因了。我们稍微修改下案例
这时候,Arrow Function中的this便变成了obj对象了,name便是Jack。
可能有人会说,不是说Arrow Function中的this是定义的时候就决定了么,怎么现在又变成了运行的时候决定了呢。
Arrow Function中的this是定义的时候就决定的,这句话是对的。
该案例中,Arrow Function中,即arrow_fn的this便是taskA的this,在定义这个arrow_fn时候便决定了,于是又回到了上面说的,taskA是一个普通的函数,普通函数的this是在运行时决定的,而此时由于bind的原因,taskA的this已经变为obj,因此arrow_fnd的this便是obj了。
说到这里,相信大家应该已经明白了Arrow Function的this的含义和具体指向了。
所以我们才说Arrow Function的this是遵守“词法作用域”的。
其他案例
我们再来看看其他案例
这里最终会打出undefined,因为getField中的this就是window,而window是没有field这个属性的,所以就是undefined了。
所以我们一般不建议对象中定义函数的时候使用Arrow Function,毕竟this就会造成错误了。所以应该这么写
这样this就是obj了。
The text was updated successfully, but these errors were encountered: