42

Array.push()などの代わりにArray.Add()のようないくつかのユーザーフレンドリーなメソッドを使用して、JavaScriptでArrayオブジェクトを拡張しようとしています...

私はこれを行うために3つの方法を実装します。残念ながら、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

3番目の方法では、Arrayオブジェクトを内部的にArray3クラスに拡張したいと思います。「プッシュは関数ではありません」や「未定義」にならないようにするにはどうすればよいですか?

ここで私は4番目の方法を追加します。

//------------- 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]);

ここでも、プロトタイプを使用する必要があります。Array4.prototypeとしてクラスコンストラクターの外で余分な行を使用しないようにしたかったのです。すべてのピースを1か所にまとめたコンパクトな定義済みクラスが必要でした。しかし、私はそれ以外の方法でそれを行うことはできないと思います。

4

8 に答える 8

33

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

使用する__proto__

(古い回答は推奨されませんが、パフォーマンスの問題が発生する可能性があります)

function SubArray() {
  var arr = [ ];
  arr.push.apply(arr, arguments);
  arr.__proto__ = SubArray.prototype;
  return arr;
}
SubArray.prototype = new Array;

これで、メソッドをに追加できますSubArray

SubArray.prototype.last = function() {
  return this[this.length - 1];
};

通常の配列のように初期化します

var sub = new SubArray(1, 2, 3);

通常のアレイのように動作します

sub instanceof SubArray; // true
sub instanceof Array; // true
于 2015-05-22T08:28:40.187 に答える
32

メソッド名は小文字にする必要があります。プロトタイプはコンストラクターで変更しないでください。

function Array3() { };
Array3.prototype = new Array;
Array3.prototype.add = Array3.prototype.push

CoffeeScriptで

class Array3 extends Array
   add: (item)->
     @push(item) 

その構文が気に入らず、コンストラクター内から拡張する必要がある場合、唯一のオプションは次のとおりです。

// 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)
      }

   });
};

あなたもこれを行うことができます

ArrayExtenstions = {
   Add: function() {

   }
}
extend(ArrayExtenstions, Array.prototype);



function Array3() { }
Array3.prototype = ArrayExtenstions;

昔は、「prototype.js」にはClass.createメソッドがありました。あなたはこれをすべて包むことができますそのような方法です

var Array3 = Class.create(Array, {
    construct: function() {

    },    
    Add: function() {

    }
});

これと実装方法の詳細については、prototype.jsソースコードをご覧ください。

于 2012-07-05T04:54:24.577 に答える
4

少し前に、 jQueryの作成者であるJohnResigが書いた本JavascriptNinjaを読みました。彼は、プレーンな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'

良いか悪いかという意味ではありません。これは、独自のArray操作方法です。利点は、を拡張しないことですArray prototypeobjそれは明白objectであり、ではないことを覚えておいてくださいArray。したがって、obj instanceof Arrayを返しfalseます。ファサードと考えobjてください。

そのコードに関心がある場合は、リスト4.10配列のようなメソッドのシミュレーションの抜粋をお読みください。

于 2016-04-12T21:22:11.593 に答える
2

prototype3番目の例では、オブジェクトにちなんで名付けられた新しいプロパティを作成しているだけですArray3new Array3どちらを実行するかを実行するとnew Array3()、そのオブジェクトが変数にインスタンス化されますlist3。したがって、問題のオブジェクトである、には有効なメソッドがないAddため、メソッドは機能しません。ご理解いただければ幸いです。thispush

編集:詳細については、 JavaScriptコンテキストの理解をご覧くださいthis

于 2012-07-05T04:35:01.663 に答える
1

ES6でも次のように使用できます。

Object.assign(Array.prototype, {
    unique() {
      return this.filter((value, index, array) => {
        return array.indexOf(value) === index;
      });
    }
});

結果:

let x = [0,1,2,3,2,3];
let y = x.unique();
console.log(y); // => [0,1,2,3]
于 2016-08-08T15:41:14.907 に答える
0

もっと複雑なことをしようとしていて、「追加」と呼ばれる「プッシュ」のエイリアスを追加するだけですか?

そうでない場合は、これを避けるのがおそらく最善でしょう。これが悪い考えであると私が提案する理由は、Arrayは組み込みのjavascriptタイプであるため、それを変更すると、すべてのスクリプトのArrayタイプに新しい「Add」メソッドが含まれるようになるためです。他のサードパーティと名前が衝突する可能性が高く、サードパーティのスクリプトがそのメソッドを失い、自分のメソッドを優先する可能性があります。

私の一般的なルールは、配列がまだどこかに存在しない場合はヘルパー関数を機能させ、非常に必要な場合にのみ配列を拡張することです。

于 2012-07-05T04:53:16.813 に答える
0

JavaScriptで配列オブジェクトを拡張することはできません。

代わりに、配列で実行される関数のリストを含むオブジェクトを定義し、これらの関数をその配列インスタンスに挿入して、この新しい配列インスタンスを返すことができます。すべきでないことはArray.prototype、リストにカスタム関数を含めるようにを変更することです。

例:

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",
}

単なるサンプルコードであり、変更して好きなように使用できます。しかし、私が従うことをお勧めする基本的な概念は同じままです。

于 2013-05-07T20:42:20.330 に答える
0
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

答えは、サポートされているすべてのブラウザで意図したとおりに機能するコンパクトな回避策です。

于 2017-05-28T18:14:25.453 に答える