技术原理

Javascript 进阶 9-2 与传统函式不同之处

这篇文章要来介绍箭头函式跟传统函式的差别~

1. 箭头函式没有 arguments 参数

之前在传统函式有介绍到,参数的传入有一个 arguments 参数会来承接所有船入的参数,并且使用**类阵列(Array-liked)**的方式记录起来。

const nums = function () {
    console.log(arguments);
}

nums(1,2,3,4,6,7,8,500,10);

https://ithelp.ithome.com.tw/upload/images/20200519/20121770Lz0A7dz7Sg.png

但箭头函式则没有这个参数,那幺当如果我们需要记录传进来的参数的时候,该怎幺办呢?

const nums = () => {
    console.log(arguments);
}

nums(1,2,3,4,6,7,8,500,10);

https://ithelp.ithome.com.tw/upload/images/20200519/20121770hnX57aIxZQ.png

这个时候就可以使用其余参数运算子来解决这个问题,利用三个点+自定义变数名称,就可以将参数的内容以阵列的方式记录在变数上噜!

const nums = (...arg) => {
    console.log(arg);
}

nums(1,2,3,4,6,7,8,500,10);

https://ithelp.ithome.com.tw/upload/images/20200519/20121770iNz9UaxkjO.png

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。

结果很明显会是:

https://ithelp.ithome.com.tw/upload/images/20200519/20121770K3rK7GohhE.png

那幺我们稍微改动一下程式码,把 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();

https://ithelp.ithome.com.tw/upload/images/20200519/20121770cBUtbQ7hJw.png

可以看到,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();

https://ithelp.ithome.com.tw/upload/images/20200519/20121770jSzsaiVvt6.png

很明显,改成箭头函式以后,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 的指向。

https://ithelp.ithome.com.tw/upload/images/20200519/20121770xTNeXHhNFW.png

3. This 不同,导致 DOM 的 This 指向也不同

const ele = document.querySelector('p');
ele.addEventListener('click', function () {
    console.log(this);
});

一般来说,这样撰写以后,点击画面上的 p 元素,this 会指向该 p 元素的 DOM。

https://ithelp.ithome.com.tw/upload/images/20200519/20121770burVdgAn7p.png

但如果用箭头函式撰写的话~

const ele = document.querySelector('p');
ele.addEventListener('click', () => {
    console.log(this);
});

https://ithelp.ithome.com.tw/upload/images/20200519/20121770BMbtT1VcOY.png

就会指向全域的物件 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, '小明', '杰伦');

https://ithelp.ithome.com.tw/upload/images/20200519/20121770z8PIruj3aM.png

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');

https://ithelp.ithome.com.tw/upload/images/20200519/20121770Bu588LzClA.png

以上就是五个传统函式与箭头函式不同的地方,其中第二点最容易搞混,要搞清楚再往下走会比较好喔!

没问题的话就继续吧!汪汪~

你也可能喜欢

发表评论

您的电子邮件地址不会被公开。 必填项已用 * 标注

提示:点击验证后方可评论!

插入图片
世界人工智能大会 投稿者
我还没有学会写个人说明!
最近文章
  • * 没有更多文章了
  • 热门搜索

    分类目录