في JavaScript ، يمكن إنشاء صفائف باستخدام مُنشئ الصفيف ، أو تم إنشاؤها بسرعة باستخدام [] ، والتي هي أيضًا الطريقة المفضلة. الصفيف عبارة عن نموذج أولي ورث من الكائن ، وليس له قيمة إرجاع خاصة للنوع ، فإنه يعيد فقط "كائن".
في JS ، يمكن القول أن كل شيء هو كائن ، وأن الصفيف هو أيضًا صفيف.
تحتوي العديد من الكائنات على العديد من الأساليب المريحة مثل Push ، Concat ، Slice ، إلخ. من المصفوفات ، ولكن إذا لم تنفذ بعض الكائنات هذه الطرق ، فلا نزال نريد استخدام هذه الوظائف. إذن ماذا علي أن أفعل؟
1. العديد من الطرق توفر تطبيقات فعالة للغاية ، ويمكننا محاكاة تطبيقاتها.
على سبيل المثال ، لا تدعم المتصفحات أدناه IE8 طريقة فهرس الصفيف. من أجل جعل فهرس دعم الصفيف ، يمكننا كتابة طريقة لأنفسنا لتنفيذ طريقة الفهرس:
(اضغط على F12 للتصحيح مع IE Browser لتحديد إصدار المتصفح إلى IE5.)
var arr = [، ، ،] ؛ if (array.prototype.indexof) {Alert ("يدعم المتصفح طريقة indexof.") ؛} else {alert ("لا يدعم متصفحك طريقة indexof.") ؛} if (! array.prototype.indexof) {array.prototype. i ++) {if (this [i] == item) {return i ؛}} return -؛}} ALERT (ARR.INDEXOF ()) ؛ ALERT (ARR.INDEXOF ()) ؛بالطبع هذه الطريقة هي القمامة للغاية. لن أكون قبيحًا في التنفيذ المحدد هنا ، وأقدم نسخة نسخة على Baidu:
إذا كنت مهتمًا ، يمكنك أن ترى كيف يتم تنفيذ محرك V8: https://github.com/v8/v8/blob/master/src/js/array.js
if (! array.prototype.indexof) {array.prototype.indexof = function (elt /*، from* /) {var len = this.length >>> ؛ var from = number (edation []) || ؛ من = (من <)؟ Math.ceil (من): Math.Floor (من) ؛ if (من <) من+= len ؛ for (؛ from <len ؛ from ++) {if (from in && this [from] === elt) return from ؛} ؛} ؛} ؛}2. ميراث الاتصال وتطبيق الأساليب
إذا كان لدينا كائن ، أليس من المزعج للغاية كتابة كل كائن لتنفيذه بنفسك؟
في اللغات عالية المستوى ، يمكننا استخدام الميراث لحل المشكلة ، مثل رمز Java التالي:
الطبقة العامة mylist <e> يمتد ArrayList <e> {public void myadd (e e) {super.add (e) ؛ system.out.println ("add:"+e) ؛}}ولكن لا يوجد مفهوم للميراث في JS. يمكننا استخدام المكالمة والتطبيق لحل هذه المشكلات.
يمكن إعادة كتابة الرمز أعلاه على النحو التالي:
var myobject = function () {} myobject.prototype.add = function () {array.prototype.push.call (هذا ، وسيطات) ؛ // إخراج الوسائط (var i = ؛ i <enduments.length ؛ i ++) {console.log ("add:هنا يمكننا أن نرى: على الرغم من أن طريقة myadd يتم تنفيذها في طريقة الميراث للغات عالية المستوى ، إلا أن طريقة myAdd يمكن أن تمر فقط معلمة واحدة الآن. إذا كنت ترغب في اجتياز معلمات متعددة ، فأنت بحاجة إلى كتابة طريقة myAdd (e [] e) ، أو حتى الفراغ العام myadd (قائمة <e> e). يمكن إجراء JS بطريقة واحدة ، باستخدام كائن الوسائط لتمثيل جميع مدخلات المعلمات ، وهو أمر صعب على اللغات عالية المستوى.
(PS ، في الواقع ، يمكنك كتابة الفراغ العام myadd (e ... e) في Java. هذه معلمة غير مؤكدة. استخدام myadd الفراغ العام (e [] e) هو نفسه)
يتم استخدام طرق الاتصال والتطبيق لتغيير مؤشر هذا المؤشر في الوظيفة. يحتوي المكالمة على معلمتين فقط ، ويستخدم تطبيقه عادة بعد معرفة عدد المعلمات. ما يلي مثال:
var obj = function (name) {this.name = name ؛} obj.prototype.getName = function () {return this.name ؛} var obj1 = new obj ("zou") ؛ var obj2 = {name: 'Andy'} ؛ var name = obj1.getname.call (obj2) ؛المرجع هو:
تطبيق (كائن ، arg1 ، arg2 ، ...)
استدعاء (كائن ، [Arg1 ، Arg2 ، ......])
يمكن أن يتبع "صفيف" واحد فقط بالمكالمة ، بما في ذلك جميع المعلمات. تطبيق السكر النحوي. إذا كنت تعرف عدد المعلمات ، فسيكون ذلك مناسبًا جدًا لاستخدام التطبيق.
يمكن أيضًا أن يكون الكائن أعلاه فارغًا أو غير محدد ، لذلك هذا الكائن هو كائن عالمي (نافذة). على سبيل المثال ، سيتم اتباع المثال أعلاه:
var name = 'goo' ؛ Alert (obj1.getName.call (null)) ؛ (في الوضع الصارم ، نظرًا لأن الكائن العالمي خالي ، سيتم إلقاء استثناء: Typeerror غير معطل: لا يمكن قراءة الخاصية "اسم" NULL)
3. Object.DefineProperty
(ملاحظة: لا تستخدم هذا النوع من الميزة أدناه IE8)
Microsoft: أضف خصائص إلى الكائنات ، أو تعديل خصائص الخصائص الموجودة.
getters ، المستقدون ،
في الواقع ، هناك أيضًا getters ووظائف setter لخصائص الكائنات في JS ، لكنني شخصياً أعتقد أن getters و setters في JS يشبهون C#.
على سبيل المثال ، يحدد الكود التالي getter/setter:
الدالة myobj () {} object.defineProperty (myobj.prototype ، 'length' ، {get: function () {return this.length_ ؛ // هذا لا يمكن أن يكون طوله.لا يمكن أن يكون المكان الذي تم التعليق عليه ، وإلا فإنه سيكون متكررًا بلا حدود.
يمكنك أيضًا إزالة المجموعة وجعل المتغير المتغير فقط.
Object.defineProperty (myobj.prototype ، 'length' ، {get: function () {return this.length_ ؛ // هذا لا يمكن أن يكون طوله.} ، /*set: function (value) {return this.length_ = value ؛}* /}) ؛ myobj.length = 3 ؛سوف يلقي هذا الرمز استثناءً: unit uniticed typeerror: لا يمكن تعيين طول خاصية #<myobj> الذي يحتوي على getter فقط.
لجعل خصائص الكائن للقراءة فقط ، يمكنك أيضًا استخدام قابلة للكتابة: خطأ.
Object.DefineProperty (myobj.prototype ، 'length' ، {bractable: false}) ؛قابلة للكتابة: FALSE لا يمكن التعايش مع GET SET ، وإلا سيتم طرح خطأ في النوع.
قابلة للتكوين: هل يمكن حذفه ببيان الحذف ، ولكن يبدو أن الخاصية القابلة للتكوين صالحة في وضع صارم. لا يزال من الممكن تنفيذ مثل هذا الرمز في الوضع غير المتخلف: (تم الإبلاغ عن خطأ في الوضع الصارم)
Object.DefineProperty (myobj.prototype ، 'length' ، {configable: false}) ؛ var obj = new myobj () ؛ delete obj.length ؛القيمة: يحدد القيمة الثابتة للكائن. القيمة: 10 ، مما يشير إلى أن القيمة الأولية لهذا الكائن هي 10.
في الوضع غير الشريطي ، لن يبلغ هذا الرمز عن خطأ ، وفي وضع صارم ، سيبلغ عن خطأ:
Object.DefineProperty (myobj.prototype ، 'length' ، {crandable: false ، value: '10 '}) ؛ var obj = new myobj () ؛ obj.length = 100 ؛يمكنك استخدام GetOwnPropertyDescriptor للحصول على هذه القيم وتعديلها. على سبيل المثال ، الآن خاصية الطول الخاصة بي هي القراءة فقط.
تشغيل مثل هذا الرمز ، ولكن حدث خطأ:
Object.DefineProperty (myobj.prototype ، 'length' ، {value: ، crandable: false ،}) ؛ var descriptor = object.getownProperTyDescriptor (myobj.prototype ، "length") ؛ descriptor.writable = true نوع غير معطل: لا يمكن إعادة تعريف الخاصية: الطولوذلك لأن القيمة الافتراضية للتكوين خاطئة. بعد استدعاء DefineProperty ، يحتوي التكوين على الخاصية الخاطئة ، لذلك لا يمكن عكسها. لا يمكن تغييره في المستقبل.
لذلك ، يجب عليك استخدام تكوين: صحيح ، ويمكن تعديل خاصية الكائن هذه. الرمز الكامل كما يلي:
object.defineProperty (myobj.prototype ، 'length' ، {value: ، crandable: false ، configable: true}) ؛ var descriptor = object.getownpropertyDescriptor (myobj.prototype ، "mense") ؛ descriptor.writable = true = ؛ var obj = new myobj () ؛ Alert (obj.length) ؛يمكنك إضافة واصف الجملة.
هذا يعني أنني قمت بتعديل هذه الخاصية ، ولا يمكنك تعديلها في المستقبل
هذه الميزة مفيدة أيضًا في كثير من الحالات. إذا كنت تستخدم الأساليب وتطبيقها ، فيجب أن يكون طول الكائن متغيرًا. إذا كانت سمة طول الكائن للقراءة فقط ، فسيتم طرح استثناء عند الاتصال بالاتصال والتطبيق.
على سبيل المثال ، لا يمكن تغيير طول كائن DomTokenList. حصلت على كائن domtokenlist ،
لكن قابلة للتكوين صحيحة ، يمكننا تعديلها بحيث يمكن تغيير خاصية الطول:
انظر ، هذا القابل للتكوين صحيح ، و setter غير محدد. دعنا نكتب طريقة مجموعة لذلك ، أليس كذلك؟
var descriptor = object.getownProperTyDescriptor (domtokenlist.prototype ، 'length') ؛ descriptor.
ثم الركض ،
تم إلقاء استثناء آخر ، RangeError غير معطل: الحد الأقصى لحجم مكدس المكالمات تجاوز (...)
هذا لأنه عندما نقوم بتعيين هذا.
لذلك ، نحتاج إلى استخدام الحذف للقضاء على تأثير سمة الطول ، أي:
var descriptor = object.getownProperTyDescriptor (domtokenlist.prototype ، 'length') ؛ deviceSor.set = function (value) {delete domtokenlist.prototype.length ؛ this.length = value ؛} object.defineProperty (domtokenlist.prototype ، 'length' ، devaccord) ؛وبهذه الطريقة ، يدعم DomTokenList أيضًا Push و POP وغيرها من العمليات.
Array.Prototype.push.call (document.body.classlist ، 'ABC')
ثم تغليف
domtokenlist.prototype.push = function () {array.prototype.push.call (document.body.classlist ، array.prototype.slice.call (وسيطات)) ؛}يتم استخدام طريقة Array.Protype.slice.Call (الوسيطات) لتحويل كائنات الوسائط إلى صفائف.