创建箭头函数是为了简化功能scope
并this
通过使其更简单来解决关键字。他们利用=>
语法,看起来像箭头。
注意:它不会替代现有功能。如果将所有函数语法替换为箭头函数,则并非在所有情况下都起作用。
让我们看一下现有的ES5语法,如果this
关键字位于对象的方法(属于对象的函数)内,则它指的是什么?
var Actor = {
name: 'RajiniKanth',
getName: function() {
console.log(this.name);
}
};
Actor.getName();
上面的代码段引用了,object
并打印出了名称"RajiniKanth"
。让我们探索下面的代码片段,看看这里指出了什么。
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
this.movies.forEach(function(movie) {
alert(this.name + " has acted in " + movie);
});
}
};
Actor.showMovies();
现在该this
关键字是否在其中method’s function
呢?
在这里,这指window object
的inner function
是它掉出来了scope
。因为this
,总是引用函数所在的所有者,在这种情况下(因为它现在不在范围内),它是窗口/全局对象。
当它在object
的方法中时- function
的所有者是对象。因此,此关键字绑定到对象。但是,当它位于函数内部时,无论是独立存在还是在另一种方法中,它将始终引用该window/global
对象。
var fn = function(){
alert(this);
}
fn(); // [object Window]
有多种方法可以解决我们ES5
自己的问题,让我们在深入探讨如何解决该问题的ES6箭头功能之前先进行研究。
通常,您将在方法的内部函数之外创建一个变量。现在,该‘forEach’
方法可以访问属性,this
从而可以访问object’s
属性及其值。
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
var _this = this;
this.movies.forEach(function(movie) {
alert(_this.name + " has acted in " + movie);
});
}
};
Actor.showMovies();
使用bind
附加的this
引用该方法的关键字method’s inner function
。
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
this.movies.forEach(function(movie) {
alert(this.name + " has acted in " + movie);
}.bind(this));
}
};
Actor.showMovies();
现在有了ES6
箭头功能,我们可以lexical scoping
以更简单的方式处理问题。
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
showMovies: function() {
this.movies.forEach((movie) => {
alert(this.name + " has acted in " + movie);
});
}
};
Actor.showMovies();
Arrow functions
更像是函数语句,除了它们bind
的this parent scope
。如果arrow function is in top scope
。this
参数引用window/global scope
,则常规函数内部的箭头函数的this参数与其外部函数相同。
With arrow
函数在创建时this
绑定到附件scope
,无法更改。新的运算符,绑定,调用和应用对此无效。
var asyncFunction = (param, callback) => {
window.setTimeout(() => {
callback(param);
}, 1);
};
// With a traditional function if we don't control
// the context then can we lose control of `this`.
var o = {
doSomething: function () {
// Here we pass `o` into the async function,
// expecting it back as `param`
asyncFunction(o, function (param) {
// We made a mistake of thinking `this` is
// the instance of `o`.
console.log('param === this?', param === this);
});
}
};
o.doSomething(); // param === this? false
在上面的示例中,我们失去了对此的控制。我们可以通过使用this
或使用变量引用来解决上述示例bind
。使用ES6,可以更轻松地管理与this
绑定的lexical scoping
。
var asyncFunction = (param, callback) => {
window.setTimeout(() => {
callback(param);
}, 1);
};
var o = {
doSomething: function () {
// Here we pass `o` into the async function,
// expecting it back as `param`.
//
// Because this arrow function is created within
// the scope of `doSomething` it is bound to this
// lexical scope.
asyncFunction(o, (param) => {
console.log('param === this?', param === this);
});
}
};
o.doSomething(); // param === this? true
什么时候不使用箭头功能
在对象文字内部。
var Actor = {
name: 'RajiniKanth',
movies: ['Kabali', 'Sivaji', 'Baba'],
getName: () => {
alert(this.name);
}
};
Actor.getName();
Actor.getName
与箭头函数来定义,但在调用它提示未定义,因为this.name
是undefined
作为上下文仍然window
。
之所以发生这种情况,是因为arrow函数将上下文与window object
...即外部作用域按词法绑定。执行this.name
等效于window.name
,未定义。
对象原型
在上定义方法时,同样的规则适用prototype object
。而不是使用箭头函数来定义sayCatName方法,这会带来错误的结果context window
:
function Actor(name) {
this.name = name;
}
Actor.prototype.getName = () => {
console.log(this === window); // => true
return this.name;
};
var act = new Actor('RajiniKanth');
act.getName(); // => undefined
调用构造函数
this
在构造调用中是新创建的对象。执行new Fn()时,的上下文constructor Fn
是一个新对象:this instanceof Fn === true
。
this
是从封闭上下文(即,使其不分配给新创建的对象的外部范围)设置的。
var Message = (text) => {
this.text = text;
};
// Throws "TypeError: Message is not a constructor"
var helloMessage = new Message('Hello World!');
具有动态上下文的回调
箭头函数context
在声明时静态绑定,无法使其动态化。将事件侦听器附加到DOM元素是客户端编程中的常见任务。事件触发以此为目标元素的处理函数。
var button = document.getElementById('myButton');
button.addEventListener('click', () => {
console.log(this === window); // => true
this.innerHTML = 'Clicked button';
});
this
是在全局上下文中定义的箭头函数中的窗口。当发生click事件时,浏览器尝试使用按钮上下文调用处理函数,但是arrow函数不会更改其预定义上下文。this.innerHTML
等同于window.innerHTML
并且没有意义。
您必须应用一个函数表达式,该表达式允许根据目标元素进行更改:
var button = document.getElementById('myButton');
button.addEventListener('click', function() {
console.log(this === button); // => true
this.innerHTML = 'Clicked button';
});
当用户单击按钮时,处理程序功能中的该按钮为按钮。从而this.innerHTML = 'Clicked button'
正确修改按钮文本以反映单击状态。
参考:https :
//dmitripavlutin.com/when-not-to-use-arrow-functions-in-javascript/
Fixed this bound to scope at initialisation
限制吗?