普通函数和箭头函数的区别
1,语法更加清晰.简洁.
2,箭头函数不会创建自己的this,所以它没有自己的this,它只会从自己的作用域链的上一层继承this。
3, 箭头函数继承而来的this指向永远不变.是继承的它定义时所处的全局执行环境, 之后不再改变
4, 箭头函数继承而来的this指向永远不变.
5, 所以, call(),apply(),bind()无法改变箭头函数中this的指向
6, 箭头函数不能作为构造函数使用.
7, 箭头函数没有自己的arguments.
8, 箭头函数没有原型prototype.
9, 箭头函数不能用作Generator函数,不能使用yeild关键字.
1,语法更加清晰.简洁.
- 普通函数: 不管是声明式函数还是表达式函数,亦或者匿名函数.都必须要关键字
function
. - 箭头函数: 采用箭头=>来定义函数。函数的参数放在=>前面的括号中,函数体跟在=>后的花括号中;
example:
// 声明式函数
function add() {
// to do...
}
// 表达式函数
const add = function () {
// todo ...
}
// 匿名函数, 配合表达式函数使用
function() {
// todo ...
}
// 箭头函数
const add = () => {
// todo ...
}
// 下面给出一个例子, 说明箭头函数较普通函数简洁很多.
const arr = [1, 2, 3, 4, 5]; // 我们使用map()把它全部转换成字符串
const newArrByArrowFunc = arr.map(v => v.toString())
const newArrByOrdinaryfunc = arr.map(function(item) {
return item.toString()
})

2, 箭头函数不会创建自己的this,所以它没有自己的this,它只会从自己的作用域链的上一层继承this。
const obj = {
name: 'Jock',
ordinal: function(){
console.log(this);
},
arrow: () => {
console.log(this);
}
};
obj.ordinal(); // {name: "Jock", ordinal: ƒ, arrow: ƒ}
obj.arrow(); // undefined
PS: 如果你在控制台打印. 箭头函数的this 是Gloabl. 这个下面会说

3, 箭头函数继承而来的this指向永远不变.是继承的它定义时所处的全局执行环境, 之后不再改变
// 我们都知道, 普通函数的 this 是谁调用,指向谁.
//但是箭头函数的 this 是继承的它定义时所处的全局执行环境, 之后不再改变
// 还是用刚刚的例子, 只是我们先定义一个name
var name = "Tom"
const obj = {
name: 'Jock',
ordinal: function(){
console.log(this);
},
arrow: () => {
console.log(this);
}
};
obj.ordinal(); // "Jock"
obj.arrow(); // "Tom"
// 注意: 我定义第一个name的时候用了var 而不是 const, 如果用了const会怎样?
const name = "Tom"
const obj = {
name: 'Jock',
ordinal: function(){
console.log(this.name);
},
arrow: () => {
console.log(this.name);
}
};
obj.ordinal(); // "Jock"
obj.arrow(); // undefined
//这个涉及到变量提升, 我会另出一篇关于 const let var 的文章
// 如果打印this, 我们会发现, 箭头函数的this指向了window,
// 也就是调用的全局. 而箭头函数指向了调用的对象 obj.
// 由于const定义的变量不能提升, 所以在全局Global下
// 没有name,即undefined.


4, 箭头函数继承而来的this指向永远不变.
以上面的内容来解释. 正常浏览器执行context(上下文)时,普通函数如果obj没有name属性(谁调用指向谁),那么name会指向全局的name, 即Tom
// 我们都知道call(), apply(), bind() 可以改变this指向
// 那么我们来试试
还是上面的例子, 注意 是用的var 定义
var name = "Tom"
const obj = {
name: 'Jock',
ordinal: function(){
console.log(this.name);
},
arrow: () => {
console.log(this.name);
}
};
// 未改变this指向时
obj.ordinal(); // "Jock"
obj.arrow(); // undefined
// 改变this指向后
obj.ordinal.call({name: "Hack"}); // 'Jock'
obj.arrow.call({name: "Hack"}); // 'Tom''
obj.ordinal.apply({name: "Hack"}); // 'Jock'
obj.arrow.apply({name: "Hack"}); // 'Tom''
obj.ordinal.bind({name: "Hack"}); // 'Jock'
obj.arrow.bind({name: "Hack"}); // () => console.log(this.name);}
再来看一个例子
const obj = {
plus: function () {
console.log(this, "this")
},
add: () => {
console.log(this, "this1")
}
}
const plus1 = obj.plus
const add1 = obj.add
obj.plus()
plus1()
obj.add()
add1()

普通函数, 谁调用, this指向了谁.
箭头函数, 第一次指向的就是全局.
6, 箭头函数不能作为构造函数使用.
这里我就不讲构造函数做了什么了. 感兴趣可以自己去查查构造函数的资料, new的时候做了什么.
因为箭头函数没有自己的this,而且一旦确定无法改变. 所以 new func()的时候,无法把this指向新创建的对象, 所以箭头函数作为构造函数使用会报错.
7, 箭头函数没有自己的arguments.
// 我们都知道普通函数传入多个参数时,我们可以用arguments 获取
(function(age,name){
console.log(arguments);
//[18,"Tom", callee: ƒ, Symbol(Symbol.iterator): ƒ]
console.log(arguments.length); //2
console.log(arguments[0]); //18
console.log(arguments[1]); //Tom
})(18,"Tom")
// 如果是箭头函数则会报错

如果是箭头函数需要获取arguments的话,参数可以使用解构运算符
((...args) => {
console.log(args); //[18,"Tom"]
})(18,"Tom")
8,箭头函数没有原型prototype
const func1 = function () {}
const func2 = () => {}
console.log(func1.prototype) // {constructor: ƒ}
console.log(func2.prototype) // undefined

9, 箭头函数不能用作Generator函数,不能使用yeild关键字.(面试被问到,为什么不能balabala....)
这条我也不是很清楚原因.当时回答原话, 好像是因为提案没有被通过, 具体的我确实没有太深入. 后面就问到Generator 和aysn/await直接的区别,用法,和场景.
有知道这题原理的coder,求评论解答.
网友评论