Closed lixiaoyan closed 9 years ago
我不确定 arrow function 上是否可以调用 call ... 不过this应是lexical绑定这一点是无疑的。
@hax arrow function 上是可以 call 的, 上面代码只不过是证明 arguments 同 this 一样是 lexical 绑定的.
@hax 事实上, 无论是 call / apply / bind 在 arrow function 上都是工作的, 只不过 this 和 arguments 是 lexical 绑定的而已. 另外多说一句, chrome(v8) 目前为止似乎还不支持 arguments 的处理.
这个应该好处理,在arrow function前记录下this和arguments的引用,替换掉执行的。
对了,还有super。
会出现super的场景么?
class A {
a() { return 'a' }
}
class B extends A {
get b() { return x => super.a() + x + 'b' }
}
console.log(new B().b('x')) // => "axb"
function A(){}
A.prototype.a = function() { return 'a' }
function B(){A.call(this)}!function(){var _4=Object.create(A.prototype);_4.constructor=B;B.prototype=_4}();
Object.defineProperty(B.prototype, "b", {get :function() { return function(x) {return A.prototype.a.call(this) + 'b'} }});
Object.keys(A).forEach(function(k){B[k]=A[k]});
console.log(new B().b())
是 ab
题外话。B extends A要求B的[[prototype]]为A。从你贴的生成代码看是复制所有属性(但是没有复制原型上的属性,这可能是个bug),但是如果有__proto__
时可以直接B.__proto__ = A
。
没错吧? 复制所有属性那里,你说的是最后一句Object.keys那里吧,实际上应该说是“继承所有静态属性”。 一开始就是继承原型了啊,寄生组合式继承,Object.create(A.prototype)那里。
Object.create(A.prototype)是子类的原型继承父类的原型,我说的是子类构造器继承父类构造器。B.__proto__ = A
之后你也不需要复制静态属性了,因为自动就继承了。
@hax __proto__
is a part of es6, not es5.
一,一
function test() {
var fn = (a, b, c) => console.log(this, arguments, a, b, c);
fn.call({name: "inner"}, 4, 5, 6);
}
编译成这样可否?
function test() {
var temp1 = this, temp2 = arguments;
var fn = (a, b, c) => { this = temp1; arguments = temp2; console.log(this, arguments, a, b, c); }
fn.call({name: "inner"}, 4, 5, 6);
}
@army8735 你确认 this
能修改...?
() => { this, arguments }
替换成
var $_this = this, $_arguments = arguments;
function() { $_this, $_arguments }
类似这样的.
另外如果不考虑仅 strict mode 的话还得处理这种情况.
() => {
{
let arguments = {};
console.log(arguments);
}
}
这时这里的 arguments
不应该被替换.
this不能改就麻烦了…… 第二个strict mode不用担心
@army8735 你是不是误解了什么... this 和 arguments 的 lexical 绑定只能通过替换 arrow function 里面的 this 和 arguments 实现. 后面那段评论的意思是并非所有情况下 arguments 都会被替换. 参考 traceur 的实现.
(function(){
(()=>{
console.log(arguments);
{
let arguments=["inner"];
console.log(arguments);
}
console.log(arguments);
})("outer");
})();
// 应该得到的输出:
// ["outer"]
// ["inner"]
// ["outer"]
// 测试浏览器: firefox 33.1
补充: 由于浏览器尚不支持 arguments 的 lexical 绑定, 所以参数调用放里面, 不影响当前这个测试.
无论是对 this 赋值还是对 arguments 赋值都不现实, 因为你无法保证代码运行环境是否在 strict mode 下, this 就不说了, 在 strict mode 下对 arguments 赋值会抛异常的. 另外就算用了变量替换, 上面那段代码也无法保证完美支持. 比如, 将上面的那个 let 套上一个 eval.
// ...
eval("let arguments=[\"inner\"];");
// ...
然后你会在 firefox 里的到一个非常坑的结果: outer / inner / inner. 我估计这大概也是 traceur 强制 strict mode 的一个原因吧.
补充: 上面两段代码均在非 strict mode 下运行.
应该是只需考虑 strict。module下的代码自动都是strict。
@army8735 __proto__
很早就有了,几乎所有引擎都早已实现了(除了IE)。ES6标准化(实现细节有变化)之后,IE11也支持了。所以可以优先使用 __proto__
。参见:https://github.com/hax/mmclass/blob/master/src/class.js#L76-L90
只能用变量替换,忽视非strict了。
https://github.com/hax/mmclass/blob/master/src/class.js#L78 pds没用到?
放弃ie11以下么,国内pc端还不行吧……
嗯,78行好象是重构代码时漏删了。
79到87行就是处理IE11以下啊。其他浏览器只要第89行就结束了。
this 与 arguments 需要处理
对比实现:
参考链接:
需要 rest 支持
上面代码应该正常解析.