سؤال

هل هناك طريقة للحصول على سلوك الحصول على / تعيين على صفيف؟ أتصور شيئا مثل هذا:

var arr = ['one', 'two', 'three'];
var _arr = new Array();

for (var i = 0; i < arr.length; i++) {
    arr[i].__defineGetter__('value',
        function (index) {
            //Do something
            return _arr[index];
        });
    arr[i].__defineSetter__('value',
        function (index, val) {
            //Do something
            _arr[index] = val;
        });
}
هل كانت مفيدة؟

المحلول

الوصول إلى مجموعة لا يختلف عن الوصول إلى الممتلكات العادية. array[0] يعني array['0'], ، حتى تتمكن من تحديد العقار مع الاسم '0' واعتراض الوصول إلى عنصر الصفيف الأول من خلال ذلك.

ومع ذلك، فإن ذلك يجعله غير عملي لجميع صفائف البداية، والمزيد من طول أو أقل طول الثابت. لا يمكنك تحديد خاصية ل "جميع الأسماء التي تحدث أعداد صحيحة" كل ذلك في إحدى المرء.

نصائح أخرى

استخدام الوكلاء, ، يمكنك الحصول على السلوك المطلوب:

var _arr = ['one', 'two', 'three'];

var accessCount = 0;
function doSomething() {
  accessCount++;
}

var arr = new Proxy(_arr, {
  get: function(target, name) {
    doSomething();
    return target[name];
  }
});

function print(value) {
  document.querySelector('pre').textContent += value + '\n';
}

print(accessCount);      // 0
print(arr[0]);           // 'one'
print(arr[1]);           // 'two'
print(accessCount);      // 2
print(arr.length);       // 3
print(accessCount);      // 3
print(arr.constructor);  // 'function Array() { [native code] }'
<pre></pre>

سيقوم منشئ الوكيل بإنشاء كائن يلف وظائف صفيف واستخدامها تسمى الفخاخ لتجاوز السلوكيات الأساسية. ال get سيتم استدعاء الدالة ل أي البحث عن الممتلكات، و doSomething() قبل إرجاع القيمة.

الوكلاء هي ميزة ES6 وهي غير مدعومة في IE11 أو أقل. يرى قائمة توافق المتصفح.

نظرت إلى مقالة جون ريسج جافا سكريبت getters و setters, ، ولكن مثال النموذج الأولي لم يعمل بالنسبة لي. بعد تجربة بعض البدائل، وجدت واحدة بدا أنها تعمل. يمكنك استخدام Array.prototype.__defineGetter__ بالطريقة الآتية:

Array.prototype.__defineGetter__("sum", function sum(){
var r = 0, a = this, i = a.length - 1;
do {
    r += a[i];
    i -= 1;
} while (i >= 0);
return r;
});
var asdf = [1, 2, 3, 4];
asdf.sum; //returns 10

عملت بالنسبة لي في Chrome و Firefox.

اتمني ان يكون مفيدا.

Object.extend(Array.prototype, {
    _each: function(iterator) {
                    for (var i = 0; i < this.length; i++)
                    iterator(this[i]);
                },
    clear: function() {
                    this.length = 0;
                    return this;
                },
    first: function() {
                    return this[0];
                },
    last: function() {
                return this[this.length - 1];
                },
    compact: function() {
        return this.select(function(value) {
                                                return value != undefined || value != null;
                                                }
                                            );
        },
    flatten: function() {
            return this.inject([], function(array, value) {
                    return array.concat(value.constructor == Array ?
                        value.flatten() : [value]);
                    }
            );
        },
    without: function() {
        var values = $A(arguments);
                return this.select(function(value) {
                        return !values.include(value);
                }
            );
    },
    indexOf: function(object) {
        for (var i = 0; i < this.length; i++)
        if (this[i] == object) return i;
        return -1;
    },
    reverse: function(inline) {
            return (inline !== false ? this : this.toArray())._reverse();
        },
    shift: function() {
        var result = this[0];
        for (var i = 0; i < this.length - 1; i++)
        this[i] = this[i + 1];
        this.length--;
        return result;
    },
    inspect: function() {
            return '[' + this.map(Object.inspect).join(', ') + ']';
        }
    }
);

من الممكن تحديد Getters و Setters للحصول على صفائف JavaScript. ولكن لا يمكنك الحصول على مقالات وقيم في نفس الوقت. انظر موزيلا توثيق:

ليس من الممكن في وقت واحد الحصول على الحصول على ملكية ممتلكات ولديها الممتلكات في الواقع قيمة

لذلك إذا قمت بتحديد الملاءم للحصول على صفيف، فأنت بحاجة إلى الحصول على صفيف ثانية للقيمة الفعلية. ما يلي مثال يوضح ذلك.

//
// Poor man's prepare for querySelector.
//
// Example:
//   var query = prepare ('#modeler table[data-id=?] tr[data-id=?]');
//   query[0] = entity;
//   query[1] = attribute;
//   var src = document.querySelector(query);
//
var prepare;
{
  let r = /^([^?]+)\?(.+)$/; // Regular expression to split the query

  prepare = function (query, base)
  {
    if (!base) base = document;
    var q  = []; // List of query fragments
    var qi = 0;  // Query fragment index
    var v  = []; // List of values
    var vi = 0;  // Value index
    var a  = []; // Array containing setters and getters
    var m;       // Regular expression match
    while (query) {
      m = r.exec (query);
      if (m && m[2]) {
        q[qi++] = m[1];
        query   = m[2];
        (function (qi, vi) {
          Object.defineProperty (a, vi, {
            get: function() { return v[vi]; },
            set: function(val) { v[vi] = val; q[qi] = JSON.stringify(val); }});
        })(qi++, vi++);
      } else {
        q[qi++] = query;
        query   = null;
      }
    }
    a.toString = function () { return q.join(''); }
    return a;
  }
}

يستخدم الرمز ثلاثة صفوفات:

  1. واحد للقيم الفعلية،
  2. واحد لقيم المشفر JSON
  3. وواحد للمسافرين.

يتم إرجاع مجموعة مع الملحقات إلى المتصل. عندما set يتم استدعاء عن طريق تعيين قيمة إلى عنصر الصفيف، يتم تحديث الصفائف التي تحتوي على القيم العادية والتشفير. متى get يحصل يسمى، فإنه يعود فقط القيمة العادية. و toString إرجاع الاستعلام الكامل الذي يحتوي على القيم المشفرة.

ولكن كما ذكر آخرون بالفعل: هذا لا معنى له فقط، عندما يكون حجم الصفيف ثابت. يمكنك تعديل العناصر الموجودة من الصفيف ولكن لا يمكنك إضافة عناصر إضافية.

لماذا لا تخلق فئة جديدة للكائنات الداخلية؟

var a = new Car();

function Car()
{
   // here create the setters or getters necessary
}

وثم،

arr = new Array[a, new Car()]

اظن انك حصلت على الفكرة.

من الممكن إنشاء Setters لكل عنصر من عناصر صفيف، ولكن هناك قيود واحد: لن تكون قادرا على تعيين عناصر الصفيف مباشرة للفهارس الموجودة خارج المنطقة التهيئة (على سبيل المثال myArray[2] = ... // wouldn't work if myArray.length < 2) استخدام الصفيف. ستعمل وظائف النمط الأسماك. (مثل دفع، البوب، لصق، التحول، Unshift.) أعطي مثالا على كيفية تحقيق هذا هنا.

يمكنك إضافة أي طريقة تريدها Array, ، عن طريق إضافة لهم إلى Array.prototype. وبعد إليك مثال يضيف Getter و STERTER

Array.prototype.get = function(index) {
  return this[index];
}

Array.prototype.set = function(index, value) {
  this[index] = value;
}

هذه هي الطريقة التي أفعلها الأشياء. سوف تضطر إلى تعديل إنشاء النموذج الأولي (أزلت قليلا من الإصدار الخاص بي). ولكن هذا سيمنحك سلوك Getter / Setter الافتراضي الذي اعتدت عليه بلغات أخرى قائمة على الفئة. تحديد Getter وليس Sedter يعني أنه سيتم تجاهل الكتابة إلى العنصر ...

أتمنى أن يساعدك هذا.

function Game () {
  var that = this;
  this._levels = [[1,2,3],[2,3,4],[4,5,6]];

  var self = {
    levels: [],
    get levels () {
        return that._levels;
    },
    setLevels: function(what) {
        that._levels = what;
        // do stuff here with
        // that._levels
    }
  };
  Object.freeze(self.levels);
  return self;
}

هذا يعطيني السلوك المتوقع من:

var g = new Game()
g.levels
/// --> [[1,2,3],[2,3,4],[4,5,6]]
g.levels[0]
/// --> [1,2,3]

تناول النقاد من Dmvaldman: يجب أن تكون الكتابة مستحيلة الآن. أعدد كتابة الكود إلى 1) عدم استخدام العناصر المهملة (__ التراجع __) و 2) عدم قبول أي كتابة (أي: الكتابة غير المنضبط) إلى عنصر المستويات. يتم تضمين STER مثال. (اضطررت إلى إضافة تباعد إلى __ التراجع بسبب الانقسام)

من طلب dmvaldmans:

g.levels[0] = [2,3,4];
g.levels;
/// --> [[1,2,3],[2,3,4],[4,5,6]]

//using setter
g.setLevels([g.levels, g.levels, 1,2,3,[9]]);
g.levels;
/// --> [[[1,2,3],[2,3,4],[4,5,6]],[[1,2,3],[2,3,4],[4,5,6]], ....]

//using setLevels
g.setLevels([2,3,4]);
g.levels;
/// --> [2,3,4]

هذه الإجابة هي مجرد امتداد للحل بناء على الوكيل. راجع الحل بالوكيل، في هذه الحبل فقط مذكورة ولكن يمكننا أيضا استخدام مجموعة كما أظهد هنا.

إشعار: الوسيطة الثالثة في المجموعة يمكن أن تحمل القيمة ...

الرمز هو التفسير الذاتي.

var _arr = ['one', 'two', 'three'];

var accessCount = 0;

function doSomething() {
  accessCount++;
}

var arr = new Proxy(_arr, {
  get: function(target, name) {
    doSomething();
    return target[name];
  },
  set: function(target, name, val) { doSomething(); target[name] = val; }
});

function print(value) {
  document.querySelector('pre').textContent += value + '\n';
}

print(accessCount);      // 0
print(arr[0]);           // 'one'
print(accessCount);      // 1
arr[1] = 10;
print(accessCount);      // 2
print(arr[1]);           // 10
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top