你能在箭头函数中绑定“ this”吗?

我已经用 ES6做了一段时间的实验,我刚刚遇到了一个小问题。

我真的很喜欢使用箭头函数,只要我可以,我就会使用它们。

但是,看起来你不能绑住他们!

函数如下:

var f = () => console.log(this);

下面是我要将函数绑定到的对象:

var o = {'a': 42};

下面是我将 f绑定到 o的方法:

var fBound = f.bind(o);

然后我可以打电话给 fBound:

fBound();

它将输出这个(o对象) :

{'a': 42}

很酷! 不错! 只是它不工作。它不输出 o对象,而是输出 window对象。

所以我想知道: 你能绑定箭头函数吗? (如果能,怎么绑定?)


我已经在 GoogleChrome48和 Firefox43中测试了上面的代码,结果是一样的。

104146 次浏览

在箭头函数中不能使用 重新绑定 this。它将始终被定义为定义它的上下文。如果你要求 this有意义,你应该使用一个正常的函数。

来自 ECMAScript 2015规范:

ArrowFunction 中对参数 super、 this 或 new.target 的任何引用都必须解析为词法封闭环境中的绑定。通常这将是一个立即封闭的函数的函数环境。

来自 MDN:

与函数表达式相比,箭头函数表达式的语法更短,并且在词法上绑定 this 值(不绑定自己的 this、参数、 super 或 new.target)。箭头函数始终是匿名的。

这意味着不能像您希望的那样将值绑定到 this

几天前我也问过同样的问题。

因为 this已经绑定,所以无法绑定值。

将不同的此作用域绑定到 ES6 = > 函数运算符

多年来,js 开发人员一直在与上下文绑定斗争,他们问为什么在 javascript 中 this会发生变化,这么多年来由于上下文绑定和在 javascript 中 this和在其他大多数 OOP 语言中 this的意义之间的差异而产生了如此多的困惑。

所有这一切让我不禁要问,为什么,为什么!为什么不重新绑定一个箭头函数!那些专门为解决所有这些问题和混乱而创建的,并避免使用 bindcall或其他任何方式来保持功能的范围。

DR

不,不能重新绑定箭头函数。

要完成 可以重新绑定箭头函数,就不能改变 this的含义。

bind仍然有函数参数的值:

((a, b, c) => {
console.info(a, b, c) // 1, 2, 3
}).bind(undefined, 1, 2, 3)()

试试这个: Http://jsbin.com/motihanopi/edit?js,console

ES6箭头函数能否真正解决 JavaScript 中的“ this”问题

上面的链接解释了箭头函数 this不会随着 bind, call, apply函数而改变。

用一个很好的例子来解释。

node v4中运行它来查看“预期”的行为,

this.test = "attached to the module";
var foo = { test: "attached to an object" };
foo.method = function(name, cb){
// bind the value of "this" on the method
// to try and force it to be what you want
this[name] = cb.bind(this); };
foo.method("bar", () => { console.log(this.test); });
foo.bar();

也许这个例子对你有帮助:

let bob = {
_name: "Bob",
_friends: ["stackoverflow"],
printFriends:(x)=> {
x._friends.forEach((f)=> {
console.log(x._name + " knows " + f);
});
}
}


bob.printFriends = (bob.printFriends).bind(null,bob);
bob.printFriends();

描述: Stijn de Witt

不能使用 bind在箭头函数中更改 this的值。但是,您可以创建一个新的常规函数,该函数执行与旧的 Arrow 函数相同的操作,然后像往常一样使用 callbind重新绑定 this

我们在这里使用一个 eval调用来重新创建作为普通函数传入的箭头函数,然后使用 call用另一个 this调用它:

const func = v => console.log(this);
const obj = {value: 10};


function arrowBindOld(context, fn) {
let arrowFn;
(function() {
arrowFn = eval(fn.toString());
arrowFn();
}).call(context);
}
arrowBindOld(obj, func);

更新

const f = v => console.log(this, v);
const o = {value: 10};


/* new */
function arrowBind(context, fn) {
const arrowFnString = fn.toString();
return (function() {
return eval(arrowFnString);
}).call(context);
}
const fBound = arrowBind(o, f);
fBound(10);


/* use prototype */
Function.prototype.arrowBind = function(context) {
const arrowFnString = this.toString();
return (function() {
return eval(arrowFnString);
}).call(context);
}
const fBoundProto = f.arrowBind(o);
fBoundProto(20);

简而言之,You 不能绑定箭头函数,但请继续阅读:

假设您有下面这个箭头函数,它在控制台上打印 this:

const myFunc = ()=> console.log(this);

所以快速修复这个问题的方法是使用普通函数,所以把它改成:

function myFunc() {console.log(this)};

然后你可以使用 bindcall或者 apply将它绑定到任何词法环境:

const bindedFunc = myFunc.bind(this);

bind的情况下调用它。

bindedFunc();

还有一些方法可以使用 eval()来做到这一点,它强烈地 不推荐

正常绑定:

tag.on("Initialized", function(tag) {
nodeValueChanged(tag, currentNode)
}.bind(currentNode))

箭头函数绑定:

tag.on("Initialized", (tag => { nodeValueChanged(tag, currentNode) }).bind(currentNode))

我认为这是更好的解决办法

var f = (vm=this) => console.log(vm);

箭头函数总是基于其最接近的非箭头函数使用 this,而不管它在哪里被调用。如果没有非箭头父对象,它总是引用全局对象。

当您使用 call/bind/application 调用 Arrow 函数时,它并不指向要传递的对象。

var obj = {a:1};
var  add=(b)=>{
return this.a + b;
// basically here this.a will be undefined as it's trying to find in one level up which is parents of this function that is window.
}


add.call(obj,2);

这就是为什么传递对象在箭头函数中不起作用。

这意味着不可能将一个对象绑定到一个箭头函数,永远不要说从来没有; 我认为一个黑客可能会工作。

function arrowToRegularFn(callback) {
let _callback = callback
const stringifiedCallback = callback.toString()
const isArrowFn = !stringifiedCallback.trim().startsWith("function")
if (isArrowFn) {
const isParamsInParantheses = stringifiedCallback.trim().startsWith("(")
const [fnParams, ...fnBody] = stringifiedCallback.split("=>")
_callback = eval("(function" + (!isParamsInParantheses ? "(" : "") + fnParams + (!isParamsInParantheses ? ")" : "") + "{" + fnBody.join("=>") + "})")
}
return _callback
}


// test cases


// our object to bind
const quiver = { score: 0 }


let arrow, regular;


// test - 1
arrow = () => this.score++
regular = arrowToRegularFn(arrow).bind(quiver)
regular()
console.log(quiver.score) // 1


// test - 2
arrow = (x, y) => this.score = x + y
regular = arrowToRegularFn(arrow).bind(quiver)
regular(1, 2)
console.log(quiver.score) // 3


// test - 3
arrow = (x, y) => { this.score = x + y }
regular = arrowToRegularFn(arrow).bind(quiver)
regular(3, 4)
console.log(quiver.score) // 7


// test - 4
arrow = function(x, y) { this.score = x + y }
regular = arrowToRegularFn(arrow).bind(quiver)
regular(5, 6)
console.log(quiver.score) // 11