何时在JavaScript中使用'Array.prototype',何时使用'this'?

5

让我们来看一下《JavaScript语言精粹》这本书中的一个例子:

Array.method('unshift', function () {
    this.splice.apply(this,[0,0].concat(Array.prototype.slice.apply(arguments)));
    return this;
});

为什么作者在某些地方使用了this.splice,而在另一些地方使用了Array.prototype.slice?
我曾尝试交换thisArray.prototype,但是出现了以下错误: TypeError: Cannot read property 'slice' of undefined 但我仍然不确定如何知道何时应该使用thisArray.prototype

1
非常相关:https://dev59.com/-mw05IYBdhLWcg3wv0R6 - deceze
这本书从来就不是学习JavaScript的好方法,而且现在已经严重过时了(将近十年)。我强烈建议你找一本更好的书来学习。 - user663031
@torazaburo 但是我从各种来源中看到这本书被推荐后,就开始阅读了它。 - Rajat Saxena
抱歉,但这本书是一些与现在无关、过时的东西的集合,而且在很多情况下是错误的。用英语打个比方,它更接近于乔叟(Chaucer)而不是莎士比亚(Shakespeare)。它主要是考古学上的兴趣。最重要的是,它完全省略了现代JS程序员每天生活中使用的非常重要的东西。 - user663031
1
@torazaburo,如果我已经读完了这本书的前九章,并且这是我第一次接触JS,您还会推荐哪些其他书籍呢? - Rajat Saxena
显示剩余2条评论
2个回答

9
在第一次调用中,this指的是调用unshift方法的数组,因此它从Array.prototype继承了splice方法。
然而,在第二次调用中,代码在一个不是数组的对象(arguments伪数组)上使用了slice方法,该对象没有slice方法。因此,在这种情况下,Crockford通过Array.prototype访问了该方法。
严格来说,他可以在第二个位置使用this.slice,像这样:
Array.method('unshift', function () {
    this.splice.apply(this,[0,0].concat(this.slice.apply(arguments)));
    return this;
});

...但这可能会误导人,因为第二个调用与当前由this引用的数组无关。


@RajatSaxena:不客气。我已经删除了一些误导性的内容(代码使用了spliceslice,但在我的原始答案中,我错误地认为它使用了两次splice)。 - T.J. Crowder

1
有时候,通过可视化关系更容易理解,这样你就会意识到在许多情况下我们有 foo.bar === Foo.prototype.bar; // true

structure of prototypes

在创建一个名为foo的实例时,构造函数Foo原型属性被设置为foo (__proto__) 的特殊引用。如果您尝试访问foo上不存在的属性,那么下一个查找该属性的位置是通过该引用进行的。
这意味着,当您期望foo没有以隐藏该对象的属性的方式进行修改时,无论您是通过foo.bar还是Foo.prototype.bar进行查找,都是相同的。
然而,正如您所看到的,不是所有东西都有相同的__proto__路径,因此您不能假设例如obj.slice将存在。这意味着,如果您没有一个Array实例但您想要进行slice操作,则必须通过您知道存在的方式引用slice,例如Array.prototype.slice

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接