箭头函数与()
计算机不智能,看见{}认为是块级作用域,不是对象,人可以分辨出这是个对象,但计算机不行,需要用()包裹{},告诉计算机{}是对象,{}里面的是对象
let foo=(a,b)=>({a:3,b:4});
// let foo=(a,b)=>{a:3,b:4};//SyntaxError: Unexpected token ':'
console.log(foo());
箭头函数与函数的区别:特性
1.this,是外层的函数作用域来决定的
2.=>不能作为构造函数来使用;bind,apply,call();不能实现
this是new出来的,不能new也就没有this
bind,apply,call();不能实现,因为没有this
3 没有arguments对象,用rest(扩展运算符)替代
4 yield命令不能生效,在generator函数中
function foo(){
console.log(this);//obj1{a:2}
return (a)=>{
console.log(this.a)
}
}
var obj1={a:2};
var obj2={a:3};
var bar=foo.call(obj1);
/*箭头函数作用域由外层作用域决定的,foo函数中的this指向的是obj1*/
bar.call(obj2);//2 bar是返回的箭头函数,给箭头函数绑定this给obj2没有用
/*没有办法以箭头函数.call的方式,来改变箭头函数的this指向*/
const person={
/*eat:function (){
}*/
eat(){
console.log(this);
},
drink:()=>{
console.log(this);
}
}
person.eat();//person对象
/*this默认window,只不过person.eat时候给转换成了person,再运行函数*/
person.drink();//window
/*箭头函数就不转了,那就走默认的window*/
<button id="button">button</button>
<script !src="">
(function (){
function Button(){
this.button=document.getElementById('button');
}
Button.prototype={
init(){
this.bindEvent();
},
bindEvent(){
// this.button.addEventListener('click',this.clickBtn.bind(this),false);
/*括号可写可不写,通过箭头函数的this指向this.button对象*/
// this.button.addEventListener('click',(e)=>{this.clickBtn(e)},false);
this.button.addEventListener('click',(e)=>this.clickBtn(e),false);
// this.button.addEventListener('click',this.clickBtn,false);
},
clickBtn(e){
console.log(e);
console.log(this);
}
}
new Button().init();
})()
</script>
function foo() {
return () => {
return () => {
return () => {
console.log("id", this.id);
}
}
}
}
var f = foo.call({id: 1});
var f1 = f.call({id: 2})()();
var f2 = f().call({id: 3})();
var f3 = f()().call({id: 4});
/*id 1 id 1 id 1*/
/*箭头函数内部没有this机智,this指向是固化的*/
/*箭头函数内部没有this机智,this指向是固化的=》函数的内部是并没有自己的this,
* 只能够通过父级作用域来获取到this,闭包的this
* 箭头函数拿着父级的this,返回箭头函数,这是个闭包*/
function foo() {
console.log(this);
return () => {
console.log(this)
return () => {
console.log(this)
return () => {
console.log(this);
console.log("id", this.id);
}
}
}
}
var f = foo.call({id: 1});
var f1 = f.call({id: 2})()();
var f2 = f().call({id: 3})();
var f3 = f()().call({id: 4});
var test = () => {
console.log(arguments);
//Uncaught ReferenceError: arguments is not defined
}
test();
function foo() {
/*这两个是一样的,箭头函数的argument拿着父级函数arguments
*相当于拿着a变量,相当于一个闭包
* 父函数*/
var a=1;
console.log(arguments); //Arguments(7)[1, 2, 3, 4, 5, 6, 7, callee: ƒ, Symbol(Symbol.iterator): ƒ]
setTimeout(() => {
/*子函数*/
console.log(a);//1
console.log(arguments);
console.log(this)//window
})
}
foo(1, 2, 3, 4, 5, 6, 7);
//Arguments(7)[1, 2, 3, 4, 5, 6, 7, callee: ƒ, Symbol(Symbol.iterator): ƒ]
闭包:一个函数的执行,导致另外一个函数的定义,会形成闭包;
foo是闭包,外层父函数是闭包
调试
closure就是闭包
foo运行,()=>{}箭头函数在foo函数中被定义,形成了闭包,子函数的scope存储父函数的AO,即使不使用父函数的变量
在这里面使用了父函数的变量
function insert(value) {
return {
into: function (array) {
return {
after: function (afterValue) {
array.splice(array.indexOf(afterValue) + 1, 0, value);
return array;
}
}
}
}
}
console.log(insert(5).into([1, 2, 3, 4, 6, 7, 8]).after(4));
/*
[1, 2, 3, 4, 5, 6, 7, 8]把5插入数组的第下标为4的地方
*/
es6简写
let insert = (value) => ({
into: (array) => ({
after: (afterValue) => {
array.splice(array.indexOf(afterValue) + 1, 0, value);
return array;
}
})
})
console.log(insert(5).into([1, 2, 3, 4, 6, 7, 8]).after(4));
/*
[1, 2, 3, 4, 5, 6, 7, 8]把5插入数组的第下标为4的地方
*/
其实是不建议这样写的,箭头函数其实是有相应的使用场景的,这里不是很复杂,如果再复杂会很麻烦,语义化不是很好,({})很像立即执行函数({})(),并不容易读懂代码
箭头函数使用场景
1简单的函数表达式,只有一行,比如仅仅是return一个计算值
简单的函数表达式,得出唯一的return的计算值,函数内部没有this的引用,递归,事件绑定、事件解绑定,用重构箭头函数的方式,是最好的
比如排序,这样简单明了,只用一行语句,非常容易读懂
[12,3,1234,1,4].sort((a,b)=>a-b);
2.内层的函数表达式,需要调用this,var self=this,bind(this),确保适当的this指向的时候
3.var args = Array.prototype.slice.call(arguments);
如果用到Array.prototype.slice.call这时想想能不能用箭头函数加展开表达式
function sortNumber() {
return Array.prototype.slice.call(arguments).sort(function(a, b) {
return a - b;
})
}
-->ES6改写
const sortNumber = (...numbers) => numbers.sort( (a, b) => a - b );
不适合用箭头函数的情况
函数声明,执行语句比较多的,还需要用到递归,需要引用函数名,事件绑定,解绑定,避免用=>