Skip to content

js解惑-Array.[method].call有什么作用 #45

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
sunmaobin opened this issue Feb 8, 2018 · 0 comments
Open

js解惑-Array.[method].call有什么作用 #45

sunmaobin opened this issue Feb 8, 2018 · 0 comments
Assignees
Milestone

Comments

@sunmaobin
Copy link
Owner

sunmaobin commented Feb 8, 2018

js解惑-Array.[method].call有什么作用

背景

最近在项目中,看到有同事写一个数组的方法的时候,习惯性的用以下写法:

* [].forEach.call(array,fn);
* [].map.call(array,fn);
* [].sort.call(array,fn);
...

我的第一个想法是,为啥对于一个数组不直接写成:

* array.forEach(fn)
* array.map(fn)
* array.sort(fn)

询问其原因后,同事的说法是:在有些书上说过,这么写保险,保证数组的方法万无一失可以调用,不报错

观点

同事的出发点没错,就是保证书写代码的健壮性。但我个人的观点是,这种不管三七二十一统一都调用 .call 来保证功能可用的方法,在一定程度上,牺牲了代码的可读性,同时给代码增加了一些冗余。

为什么这么说呢?我们先看看同事的这个 万无一失 的担忧在哪里。

问题

我们知道在js中有一种结构叫:类数组(array-like),这是怎么样的一种结构呢?就是:表现形式上像数组,但是却没有数组的方法。

比如:

  • 在函数体内有个参数 arguments 就是获取所有的参数,这个参数获取的结果像是一个数组,但是却没有数组的方法。

  • 在老的浏览器中,使用方法 document.querySelectorAll 获取到所有Dom节点,如果要遍历,就不能直接使用数组forEach方法(最新的Chrome、Firefox已经不存在这个问题了)。

结论

综上所述,只有我们遇到 类数组 的时候,再调用数组的 .call 将类数组转换为一个真正的数组,然后使用数组提供的方法。如果我们明确知道这就是一个数组,就没必要再 call 转换一次了,实在影响代码可读性。

基本功

  • callapply 都算是继承的一种写法,[].map.call(a1,fn) 就是将数组的map方法继承给a1,并且调用这个map方法;
  • [].map.callArray.prototype.map.call 是相同的,几乎没啥差异,性能上也差不多,见这里的测评;
  • 同上我们常用的 Object.prototype.toString.call 也可以写成 ({}).toString.call,都是可以的,只所以写成 ({}) 是由于不写的话,就成了 }. 而不是对象 {}

@sunmaobin sunmaobin added this to the 2018年 milestone Feb 8, 2018
@sunmaobin sunmaobin self-assigned this Feb 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant