这篇文章要来介绍箭头函式跟传统函式的差别~
1. 箭头函式没有 arguments 参数
之前在传统函式有介绍到,参数的传入有一个 arguments 参数会来承接所有船入的参数,并且使用**类阵列(Array-liked)**的方式记录起来。
const nums = function () { console.log(arguments);}nums(1,2,3,4,6,7,8,500,10);
但箭头函式则没有这个参数,那么当如果我们需要记录传进来的参数的时候,该怎么办呢?
const nums = () => { console.log(arguments);}nums(1,2,3,4,6,7,8,500,10);
这个时候就可以使用其余参数运算子来解决这个问题,利用三个点+自定义变数名称,就可以将参数的内容以阵列的方式记录在变数上噜!
const nums = (...arg) => { console.log(arg);}nums(1,2,3,4,6,7,8,500,10);
2. This 绑定的差异
箭头函式没有自己的 This,怎么说呢?
我们先来看看範例~
var myName = '全域';var person = { myName: '小明', callName: function () { console.log('1', this.myName); setTimeout(function () { console.log('2', this.myName); console.log('3', this); }, 10); }}person.callName();
看完这样的程式码,我们可以知道 callName 这个函式中,this的指向会是 person 这个物件。
另外,setTimeout 因为传入的是 callback function ,所以这里面的作用域的 this 指向是全域的物件 window。
结果很明显会是:
那么我们稍微改动一下程式码,把 callback function 改成箭头函式的写法,看看 this 会怎么指向~
var myName = '全域';var person = { myName: '小明', callName: function () { console.log('1', this.myName); setTimeout(() => { console.log('2', this.myName); console.log('3', this); }, 10); }}person.callName();
可以看到,this 的指向变成了外层作用域的 person。
那么这个时候,再把 callName 的传统函式也改成箭头函式的写法的话呢?
var myName = '全域';var person = { myName: '小明', callName: () => { console.log('1', this.myName); setTimeout(() => { console.log('2', this.myName); console.log('3', this); }, 10); }}person.callName();
很明显,改成箭头函式以后,this的指向就跑到全域的物件 window 身上。
而且不管埋几层都一样~
var odin = '1';var obj = { odin: '2', arrfn: () => { console.log('2',this, this.odin) setTimeout(() => { console.log('2-setTimeout',this, this.odin) }, 10); }, obj: { odin: '3', arrfn: () => console.log('3',this, this.odin), obj: { odin: '4', arrfn: function () { console.log('4',this, this.odin)}, obj: { odin: '5', arrfn: function () { console.log('5',this, this.odin) setTimeout(() => { console.log('5-setTimeout',this, this.odin) }, 10); }, } } }};obj.arrfn();obj.obj.arrfn();obj.obj.obj.arrfn();obj.obj.obj.obj.arrfn();
只是如果改成传统函式的话,规则又会跟之前的一样,在被呼叫的时候,前一个的物件为 this 的指向。
3. This 不同,导致 DOM 的 This 指向也不同
const ele = document.querySelector('p');ele.addEventListener('click', function () { console.log(this);});
一般来说,这样撰写以后,点击画面上的 p 元素,this 会指向该 p 元素的 DOM。
但如果用箭头函式撰写的话~
const ele = document.querySelector('p');ele.addEventListener('click', () => { console.log(this);});
就会指向全域的物件 window 身上。
4. 也无法透过 call, apply, bind 重新给予 this 的指向
因为箭头函式没有自己的 this,所以就算使用 call, apply, bind 重新给予 this 的指向,也无法改变。
const family = { myName: '小明家'};const fn = (para1, para2) => { console.log(this, para1, para2);};fn.call(family, '小明', '杰伦');
5. 不具有 prototype,故无法作为建构函式使用
const Fn = function (a) { this.a = a;}const ArrowFn = (a) => { this.a = a;}console.log('Fn', Fn.prototype);console.log('ArrowFn', ArrowFn.prototype);const instanceFn = new Fn('a');const instanceArrowFn = new ArrowFn('a');
以上就是五个传统函式与箭头函式不同的地方,其中第二点最容易搞混,要搞清楚再往下走会比较好喔!
没问题的话就继续吧!汪汪~