Javascript中的Array.prototype.reverse和Array.reverse有什么区别

What is the difference between Array.prototype.reverse and Array.reverse in Javascript?

本文关键字:Array reverse 什么 区别 prototype Javascript 中的      更新时间:2023-09-26

我的问题涉及向现有字符串构造函数添加新方法的应用程序。在Stoyan Stefanov的Javascript面向对象程序中,有一个使用Array构造函数的.reverse()方法为String构造函数创建一个的示例。下面是示例:

String.prototype.reverse = function() {
     return Array.prototype.reverse.apply(this.split('')).join('');
}

我认为数组的 .reverse() 方法直接属于数组的对象。事实上,当我尝试用这个语句做第二段代码时:

String.prototype.reverse = function() {
     return Array.reverse.apply(this.split('')).join(''); //WITHOUT the .prototype
}
var rev = "karunesh".reverse(); //applying the code here

我在Firebug控制台中收到一个错误,指出:"TypeError:调用函数Array.reverse时缺少参数0"。这对我来说没有任何意义。

当然,如果我重新添加 .prototype,它工作得很好。

另外,如果我必须调用原型才能从 Array 对象访问 .reverse() 方法,那么我是否必须对 Javascript 中的任何内置对象执行此操作?

提前感谢您的帮助!

是不是我

必须调用原型才能从数组对象访问 .reverse() 方法

不。要访问对象上的方法,只需使用点表示法访问它。你想做的只是

return this.split('').reverse().join('');

这正是apply(或call)所做的:

var arr = this.split('');
return arr.reverse.apply(arr).join('');

最后arr.reverse === Array.prototype.reverse因为这是Array对象继承的地方。您不是在Array构造函数对象本身上访问 reverse 方法,而是通过其原型访问所有Array实例共享的属性。然而,你几乎不需要显式使用原型对象,只有当你处理的对象不是Array实例(不共享原型)时,比如arguments对象或NodeList

TypeError: missing argument 0 when calling function Array.reverse .这对我来说没有任何意义。

Array.reverse是一种非标准Array通用方法,仅在 Firefox 中可用。其目的是简化在其他对象上应用 Array 原型方法的构造,并且它确实将类似数组的对象作为第一个参数。举个例子:

Array.reverse([0, 1]) // [1, 0]

相当于

Array.prototype.reverse.apply([0, 1]);

但是,您正在做

Array.reverse.apply([…]/*, undefined*/)

它使用(不相关的)this值的数组调用 Array.reverse 函数,没有实际参数,相当于

Array.prototype.reverse.apply(undefined)

这抛出了合法的例外。

Array.reverse是未定义的(至少在Chrome 29中) - Array.prototype.reverse是一个函数,它将反转调用它的"可迭代"的顺序。

这里要注意的关键是,Array不像你在 Java 中那样是一个类 - 而是一个构造函数

[].constructor === Array;
// true

Arrayprototype 属性实际上是为任何特定的Array实例提供行为的原因:

Object.getPrototypeOf([]) === Array.prototype;
// true
// Bad idea, just for an example
var guys = ['Tom', 'Harry', 'Richard'];
Array.prototype.exclaim = function() {
    return this.join(", ") + "?!?!?!";
}; 
guys.exclaim();
// Tom, Harry, Richard?!?!?!

这里的关键是JavaScript使用基于原型的面向对象模式,而不是你更可能熟悉的经典模式。 JavaScript 没有包含所有行为但与实例不同的"类",而是具有对象,这些对象可以是其他对象的"原型",为子对象提供数据和行为。

// Totally licit OO pattern in JavaScript
var prototypeClass = {
    method1: function() { console.log("Hello from method 1!"); },
    method2: function() { console.log("Hello from method 2!"); },
    classData: 42 
};
var prototypeInstance = Object.create(prototypeClass);
prototypeInstance.method1()  // Hello from method 1!
prototypeInstance.classData  // 42
// And you can modify the class after
// instantiating instances and the changes
// will be picked up by the instances
prototypeClass.happyPrimes = "Don't they teach recreational mathematics anymore?";
prototypeInstance.happyPrimes // The quote from 42