-
Notifications
You must be signed in to change notification settings - Fork 9k
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的理解几乎完全是错误的 #150
Comments
首先,这种写法在JS中公认的名称就是箭头函数。 BTW:我自己用的时候,如果需要用到this,我尽量避免使用箭头函数。 |
@darkrainChn,首先,感谢你阅读了《ES6 标准入门》,并写了这么详细和深入的反馈。 “箭头函数”(arrow function)是规格里面的用语。事实上,整个规格里面一次也没有提到
这句话是对的,并没有写错。 function foo(){
setTimeout(() => {
console.log("id:", this.id)
}, 100);
}
foo.call({id:42}); 请问,上面代码的 你认为,答案是后者。这是不对的。 因为,这个例子中,箭头函数位于 我对上面这个例子,做了一下修改。 function foo() {
setTimeout( () => {
console.log("id:", this.id);
},100);
}
var id = 21; // 加入这行
foo.call( { id: 42 } ); 请问,上面两个 你举的其他例子,都有这个问题。 你把箭头函数所在的函数与箭头函数本身混淆了。 最后,我再举一个例子。 请问,下面的代码运行结果是什么? function foo() {
return () => {
return () => {
return () => {
console.log("id:", this.id);
};
};
};
}
var f = foo.call({id: 1});
var t1 = f.call({id: 2})()();
var t2 = f().call({id: 3})();
var t3 = f()().call({id: 4}); |
原描述是比较有歧义性,一句话形容就是this指向当前所在function scope(不包括arrow function)… |
之前看过一个文章说箭头函数是没有this的,你在箭头函数里使用this就像使用普通变量一样,在箭头函数的scope内找不都会一直向父scope寻找。 |
第一段代码。调用处的 你调用 第二段代码。调用处的 谁告诉你
|
当我看到排版乱的一塌糊涂的时候,我就认为他提出的异议一定是错的了。。。而且并不想知道为什么。 |
这句话就是箭头函数的精髓
这一句说的太模糊了,最好改成,总是指向所在函数运行时的this |
@darkrainChn 同学确实把箭头函数和箭头函数的定义函数弄混淆了,不过 @ruanyf
这样的说法确实不准确,不过也不是是等同于
在ecma262规范中,箭头函数初始化到时候,会设置[ThisMode]为lexical http://www.ecma-international.org/ecma-262/6.0/index.html#sec-functioninitialize
明确的规定,箭头函数根本没有自身的this绑定
在函数执行前绑定this的时候,传入的thisArgument会被直接忽略
也就是说箭头函数本身没法修改this,所以对this访问永远是它继承外部上下的this,按照babel的实现来说,在箭头函数内部没有this引用的时候,默认编译成这样
但是如果箭头函数内部使用了this,就成了
这个实现是符合标准的,全程没有绑定这回事。
这句话完全正确,而且语言是通过忽略对箭头函数的所有绑定操作来实现的,而不是简单的返回一个绑定this的闭包。 |
箭头函数的 |
我也补充一下,箭头函数里不但没有 this,也没有 arguments, super …… 参考资料: 我挺喜欢在 MDN 查阅 web 开发技术资料 |
在 Chrome 48 里测试了一下,虽然内部实现不是简单的闭包,也不尽等同于 function 的 bind。但是最终在使用时,箭头函数内的 this 就像是闭包传入的一样。 不知道这样理解有没有问题。 |
@JonasGao 上面 MDN 的那个网址有个示例很好理解: function Person() {
var self = this; // Some choose `that` instead of `self`.
self.age = 0;
setInterval(function growUp() {
self.age++;
}, 1000);
} 在使用感觉上可以说是等同于之前经常写的 |
词法作用域 |
箭头函数就不是函数,他也就没有了自己的this,想要完全理解this,就得从汇编说起了。高级语言到汇编代码 |
从js的角度来理解this根本就是不合理的 |
哈?我想问下,这个call方法是不是写错了?这个call第一个参数不是传入this的嘛, foo.call( { id: 42 } ) 改成 foo.call(null, { id: 42 } ); ? |
|
docs(function/arrow fucntion): edit ruanyf#150
docs(function/arrow fucntion): edit ruanyf#150 bed12f7
没写错,就是将对象{id:42}当做函数的this,来调用了foo。call方法的后续参数是作为函数参数传入的 函数本身没有接收参数 |
this在node的全局下分两种情况:1、仅仅只是打印this(console.log(this))输出的是这个模块module.exports的对象 |
我原来的观点有误,修改掉吧。
我在发此文之前,曾经考虑过到底是我对原文理解有偏差,还是原文有误。最后判断是原文有误,现在看来是我错误判断了。
前面我也写到过以下文字——
这里说的lambda表达式的“定义时”,指的是代码运行过程中“遇到”lambda表达式的时候,它和代码的上下文没有关系,而是和运行时的上下文有关。
我们可以把lambda表达式看成一个变量,在代码运行“遇到”(看见)它之前,这个变量是未定义的;遇到的时候,就会把运行时的上下文绑定在展开函数的this上。此时lambda表达式内部的操作并没有被执行,它作为一个已经被定义并绑定了this的函数实体存在,等待被实际调用。
这里强调我也强调了函数定义是一个动态的概念,是外层代码执行时才产生了箭头函数的定义。之所以会觉得原文有问题,是因为“定义”这个词配合上“外层”的概念,很容易让人理解为:原文提到的“定义”是一个代码层面的概念,并且是与代码书写位置有关的,而不是一个“运行时”的概念。所以我会认为原文是错的。
现在再看这个问题,其实在这方面我们的观点是一致的,即箭头函数的this是它真正被定义时候的“运行时”上下文,而不是箭头函数实际使用(即内部语句被执行)时的上下文。结果对于原文理解不同,造成对原文错误的判断评价。
上面说的是一个理解问题,但接下来说的就是我本身的错误了。
对于“所有的箭头函数都没有自己的this,都指向外层”这句话,经过其他人的解释,我已经知道这是正确的表述了。而我对于箭头函数的展开:
var f = () => 5;
var f = function(){return 5;}.bind(this);
并不符合真正的实现机制。我这种展开方式,只是看上去效果与箭头函数差不多,除了这种展开后的函数可以被用作对象构造函数这一点差异外,不能再手动指定this、不能重新绑定其他的this,这个特性则是相同的。这种展开只能说是一种近似方式,它并不等价于原箭头函数,只是可能可以作为将代码改写为低版本时的一种实现方式。
我前面还提到扩展运算符所谓的“逆运算”问题,现在看来也只是理解方式不同造成的困惑,并不能说原书有错。
至于提到的另外2个小问题,目前看来确实是问题,但也只是小问题而已。回头找个时间再把它们写出来。
The text was updated successfully, but these errors were encountered: