Javascript 在javascript中扩展Array对象的方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11337849/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Ways to extend Array object in javascript
提问by demosthenes
i try to extend Array object in javascript with some user friendly methods like Array.Add() instead Array.push() etc...
我尝试使用一些用户友好的方法(例如 Array.Add() 而不是 Array.push() 等)在 javascript 中扩展 Array 对象...
i implement 3 ways to do this. unfortunetly the 3rd way is not working and i want to ask why? and how to do it work.
我实现了 3 种方法来做到这一点。不幸的是,第三种方式不起作用,我想问一下为什么?以及如何做到这一点。
//------------- 1st way
Array.prototype.Add=function(element){
this.push(element);
};
var list1 = new Array();
list1.Add("Hello world");
alert(list1[0]);
//------------- 2nd way
function Array2 () {
//some other properties and methods
};
Array2.prototype = new Array;
Array2.prototype.Add = function(element){
this.push(element);
};
var list2 = new Array2;
list2.Add(123);
alert(list2[0]);
//------------- 3rd way
function Array3 () {
this.prototype = new Array;
this.Add = function(element){
this.push(element);
};
};
var list3 = new Array3;
list3.Add(456); //push is not a function
alert(list3[0]); // undefined
in 3rd way i want to extend the Array object internally Array3 class. How to do this so not to get "push is not a function" and "undefined"?
在第三种方式中,我想在内部扩展 Array 对象 Array3 类。如何做到这一点,以免“推送不是函数”和“未定义”?
Here i add a 4th way.
在这里,我添加了第四种方式。
//------------- 4th way
function Array4 () {
//some other properties and methods
this.Add = function(element){
this.push(element);
};
};
Array4.prototype = new Array();
var list4 = new Array4();
list4.Add(789);
alert(list4[0]);
Here again i have to use prototype. I hoped to avoid to use extra lines outside class constructor as Array4.prototype. I wanted to have a compact defined class with all pieces in one place. But i think i cant do it otherwise.
在这里,我必须再次使用原型。我希望避免在类构造函数之外使用额外的行作为 Array4.prototype。我想要一个紧凑的定义类,所有部分都放在一个地方。但我认为我不能这样做。
采纳答案by SMathew
Method names should be lowercase. Prototype should not be modified in the constructor.
方法名称应为小写。不应在构造函数中修改原型。
function Array3() { };
Array3.prototype = new Array;
Array3.prototype.add = Array3.prototype.push
in CoffeeScript
在 CoffeeScript 中
class Array3 extends Array
add: (item)->
@push(item)
If you don't like that syntax, and you HAVE to extend it from within the constructor, Your only option is:
如果您不喜欢这种语法,并且必须从构造函数中扩展它,那么您唯一的选择是:
// define this once somewhere
// you can also change this to accept multiple arguments
function extend(x, y){
for(var key in y) {
if (y.hasOwnProperty(key)) {
x[key] = y[key];
}
}
return x;
}
function Array3() {
extend(this, Array.prototype);
extend(this, {
Add: function(item) {
return this.push(item)
}
});
};
You could also do this
你也可以这样做
ArrayExtenstions = {
Add: function() {
}
}
extend(ArrayExtenstions, Array.prototype);
function Array3() { }
Array3.prototype = ArrayExtenstions;
In olden days, 'prototype.js' used to have a Class.create method. You could wrap all this is a method like that
在过去,'prototype.js' 曾经有一个 Class.create 方法。你可以把所有这些都包装成这样的方法
var Array3 = Class.create(Array, {
construct: function() {
},
Add: function() {
}
});
For more info on this and how to implement, look in the prototype.js source code
有关此以及如何实现的更多信息,请查看prototype.js 源代码
回答by laggingreflex
ES6
ES6
class SubArray extends Array {
last() {
return this[this.length - 1];
}
}
var sub = new SubArray(1, 2, 3);
sub // [1, 2, 3]
sub instanceof SubArray; // true
sub instanceof Array; // true
Using __proto__
使用 __proto__
(old answer, not recommended, may cause performance issues)
(旧答案,不推荐,可能会导致性能问题)
function SubArray() {
var arr = [ ];
arr.push.apply(arr, arguments);
arr.__proto__ = SubArray.prototype;
return arr;
}
SubArray.prototype = new Array;
Now you can add your methods to SubArray
现在您可以将您的方法添加到 SubArray
SubArray.prototype.last = function() {
return this[this.length - 1];
};
Initialize like normal Arrays
像普通数组一样初始化
var sub = new SubArray(1, 2, 3);
Behaves like normal Arrays
表现得像普通数组
sub instanceof SubArray; // true
sub instanceof Array; // true
回答by roland
A while ago I read the book Javascript Ninjawritten by John Resig, the creator of jQuery.
He proposed a way to mimic array-like methods with a plain JS object. Basically, only length
is required.
不久前,我阅读了jQuery的创建者John Resig撰写的Javascript Ninja一书。他提出了一种用普通 JS 对象模拟类数组方法的方法。基本上,只需要。length
var obj = {
length: 0, //only length is required to mimic an Array
add: function(elem){
Array.prototype.push.call(this, elem);
},
filter: function(callback) {
return Array.prototype.filter.call(this, callback); //or provide your own implemetation
}
};
obj.add('a');
obj.add('b');
console.log(obj.length); //2
console.log(obj[0], obj[1]); //'a', 'b'
I don't mean it's good or bad. It's an original way of doing Array
operations. The benefit is that you do not extend the Array prototype
.
Keep in mind that obj
is a plain object
, it's not an Array
. Therefore obj instanceof Array
will return false
. Think obj
as a fa?ade.
我的意思不是说它是好是坏。这是一种原始的Array
操作方式。好处是您无需扩展Array prototype
. 请记住,这obj
是一个普通的object
,它不是一个Array
. 因此obj instanceof Array
会返回false
。认为obj
是一种门面。
If that code is of interest to you, read the excerpt Listing 4.10 Simulating array-like methods.
如果您对该代码感兴趣,请阅读代码清单 4.10 模拟类似数组的方法。
回答by elclanrs
In your third example you're just creating a new property named prototype
for the object Array3
. When you do new Array3
which should be new Array3()
, you're instantiating that object into variable list3
. Therefore, the Add
method won't work because this
, which is the object in question, doesn't have a valid method push
. Hope you understand.
在您的第三个示例中,您只是创建了一个以prototype
object命名的新属性Array3
。当您执行new Array3
which should be 时new Array3()
,您正在将该对象实例化为 variable list3
。因此,该Add
方法将不起作用,因为this
所讨论的对象没有有效的方法push
。希望你能理解。
Edit:Check out Understanding JavaScript Contextto learn more about this
.
编辑:查看了解 JavaScript 上下文以了解有关this
.
回答by duyker
Are you trying to do something more complicated then just add an alias for "push" called "Add"?
您是否想做一些更复杂的事情,然后为“推送”添加一个名为“添加”的别名?
If not, it would probably be best to avoid doing this. The reason I suggest this is a bad idea is that because Array is a builtin javascript type, modifying it will cause all scripts Array type to have your new "Add" method. The potential for name clashes with another third party are high and could cause the third party script to lose its method in favour of your one.
如果没有,最好避免这样做。我建议这是一个坏主意的原因是因为 Array 是一个内置的 javascript 类型,修改它会导致所有脚本 Array 类型都有新的“添加”方法。与另一第三方发生名称冲突的可能性很高,并可能导致第三方脚本失去其方法而转而支持您的脚本。
My general rule is to make a helper function to work on the Array's if it doesnt exist somewhere already and only extend Array if its extremely necessary.
我的一般规则是创建一个辅助函数来处理数组,如果它在某处不存在,并且只有在非常必要时才扩展数组。
回答by Boopathi Rajaa
You CANNOT extend the Array Object in JavaScript.
你不能在 JavaScript 中扩展数组对象。
Instead, what you can do is define an object that will contain a list of functions that perform on the Array, and inject these functions into that Array instance and return this new Array instance. What you shouldn't do is changing the Array.prototype
to include your custom functions upon the list.
相反,您可以做的是定义一个对象,该对象将包含在 Array 上执行的函数列表,并将这些函数注入该 Array 实例并返回这个新的 Array 实例。您不应该做的是更改Array.prototype
以将您的自定义函数包含在列表中。
Example:
例子:
function MyArray() {
var tmp_array = Object.create(Array.prototype);
tmp_array = (Array.apply(tmp_array, arguments) || tmp_array);
//Now extend tmp_array
for( var meth in MyArray.prototype )
if(MyArray.prototype.hasOwnProperty(meth))
tmp_array[meth] = MyArray.prototype[meth];
return (tmp_array);
}
//Now define the prototype chain.
MyArray.prototype = {
customFunction: function() { return "blah blah"; },
customMetaData: "Blah Blah",
}
Just a sample code, you can modify it and use however you want. But the underlying concept I recommend you to follow remains the same.
只是一个示例代码,您可以修改它并随意使用。但是我建议您遵循的基本概念保持不变。
回答by selahattinunlu
You can also use this way in ES6:
你也可以在 ES6 中使用这种方式:
Object.assign(Array.prototype, {
unique() {
return this.filter((value, index, array) => {
return array.indexOf(value) === index;
});
}
});
Result:
结果:
let x = [0,1,2,3,2,3];
let y = x.unique();
console.log(y); // => [0,1,2,3]
回答by Neni
var SubArray = function() {
var arrInst = new Array(...arguments); // spread arguments object
/* Object.getPrototypeOf(arrInst) === Array.prototype */
Object.setPrototypeOf(arrInst, SubArray.prototype); //redirectionA
return arrInst; // now instanceof SubArray
};
SubArray.prototype = {
// SubArray.prototype.constructor = SubArray;
constructor: SubArray,
// methods avilable for all instances of SubArray
add: function(element){return this.push(element);},
...
};
Object.setPrototypeOf(SubArray.prototype, Array.prototype); //redirectionB
var subArr = new SubArray(1, 2);
subArr.add(3); subArr[2]; // 3
The answer is a compact workaround which works as intended in all supporting browsers.
答案是一种紧凑的解决方法,它在所有支持的浏览器中都能按预期工作。