En JavaScript, las matrices se pueden crear utilizando el constructor de matriz, o se crean rápidamente usando [], que también es el método preferido. La matriz es un prototipo heredado del objeto, y no tiene un valor de retorno especial para TypeOf, solo devuelve 'objeto'.
En JS, se puede decir que todo es un objeto, y una matriz también es una matriz.
Muchos objetos tienen muchos métodos convenientes, como Push, Concat, Slice, etc. de matrices, pero si algunos objetos no implementan estos métodos, aún queremos usar estas funciones. Entonces, ¿qué debo hacer?
1. Muchos métodos proporcionan implementaciones muy eficientes, y podemos simular sus implementaciones.
Por ejemplo, los navegadores por debajo de IE8 no admiten el método del índice de matriz. Para hacer el índice de soporte de matriz, podemos escribir un método nosotros mismos para implementar el método indexOf:
(Presione F12 para depurar con el navegador IE para seleccionar la versión del navegador a IE5).
var arr = [,,,]; if (array.protype.indexof) {alerta ("Su navegador admite el método IndexOf.");} else {alert ("Su navegador no admite índice.");} if (! Array.Prototype.indexof) { {if (this [i] == item) {return i;}} return -;}} alert (arr.indexof ()); alert (arr.indexof ());Por supuesto, este método es muy basura. No seré feo en la implementación específica aquí y proporcionaré una versión de copia en Baidu:
Si está interesado, puede ver cómo se implementa el motor 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 (argumentos []) || ; de = (de <)? Math.ceil (from): math.floor (from); if (from <) from+= len; for (; from <len; from ++) {if (from in this && this [from] === elt) return de;} return -;};}2. Métodos de herencia y aplica
Si tenemos un objeto, ¿no es muy problemático escribir cada objeto para implementarlo usted mismo?
En idiomas de alto nivel, podemos usar la herencia para resolver el problema, como el siguiente código Java:
Public Class MyList <E> extiende ArrayList <E> {public void myadd (e e) {super.add (e); system.out.println ("add:"+e);}}Pero no hay un concepto de herencia en JS. Podemos usar llamadas y aplicar para resolver tales problemas.
El código anterior se puede reescribir como:
var myObject = function () {} myObject.prototype.add = function () {array.prototype.push.call (this, argumentos); // Útiles argumentos para (var i =; i <arguments.length; i ++) {console.log ("Agregar:"+argumentos [i]);}} var obj = newObject (); Obj); Obj); Obj); Obj); Obj);Aquí podemos ver: aunque el método MyAdd se implementa en el método de herencia de los idiomas de alto nivel, el método MyAdd solo puede pasar un parámetro ahora. Si desea aprobar múltiples parámetros, debe escribir otro método de MyAdd (E [] E) público, o incluso el método public void myAdd (List <E> E). JS se puede hacer con un método, utilizando argumentos objeto para representar todos los parámetros de entrada, lo cual es difícil para los idiomas de alto nivel.
(PD, de hecho, puedes escribir públicos void myadd (e ... e) en java. Este es un parámetro incierto. El uso del público vacío myadd (e [] e) es el mismo)
Los métodos de llamada y aplicación se utilizan para cambiar el puntero de este puntero en la función. La llamada tiene solo dos parámetros, y la aplicación generalmente se usa después de conocer el número de parámetros. El siguiente es un ejemplo:
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); alerta);La referencia es:
Aplicar (Object, Arg1, Arg2, ...)
llamar (objeto, [arg1, arg2, ......])
La llamada solo puede seguir una "matriz", incluidos todos los parámetros. Aplicar es un azúcar sintáctico. Si sabe el número de parámetros, será muy conveniente de usar Aplicar.
El objeto anterior también puede ser nulo o indefinido, por lo que este objeto es objeto global (ventana). Por ejemplo, se seguirá el ejemplo anterior:
var name = 'goo'; alert (obj1.getName.call (null)); (En modo estricto, dado que el objeto global es nulo, se lanzará una excepción: no capturado typeError: no puede leer la propiedad 'nombre' de nulo)
3. Object.defineProperty
(Nota: no use este tipo de característica debajo de IE8)
Microsoft: agregue propiedades a los objetos o modifique las propiedades de las propiedades existentes.
Getters, setters,
De hecho, también hay funciones de Getters y Setter para las propiedades de los objetos en JS, pero personalmente creo que los Getters y Setters en JS son más como C#.
Por ejemplo, el siguiente código define un getter/setter:
function myobj () {} object.defineProperty (myobj.prototype, 'longitud', {get: function () {return this.length_; // esto no puede ser longitud.}, set: function (valor) {return this.length_ = value;}});El lugar comentado no puede ser longitud, de lo contrario será infinitamente recursivo.
También puede eliminar el set y hacer la longitud de la variable de solo lectura.
Objeto.defineProperty (myobj.prototype, 'longitud', {get: function () {return this.length_; // Esto no puede ser longitud.}, /*Set: function (valor) {return this.length_ = valor;}* /}); myobj.length = 3;Este código lanzará una excepción: TipoRor no capturado: no se puede establecer la longitud de la propiedad de #<syobj> que solo tiene un obtonente.
Para que las propiedades del objeto solo sean lectores, también puede usar Writing: False.
Object.defineProperty (myobj.prototype, 'longitud', {witable: false});WRATITY: False no puede coexistir con Get Set, de lo contrario se lanzará un error de tipo.
Configurable: se puede eliminar con la instrucción Eliminar, pero la propiedad configurable parece ser válida en modo estricto. Dicho código aún se puede ejecutar en modo no rictamente: (informó un error en modo estricto)
Objeto.defineProperty (myobj.prototype, 'longitud', {configurable: false}); var obj = new Myobj (); eliminar obj.length;Valor: Especifica el valor fijo del objeto. Valor: 10, lo que indica que el valor inicial de este objeto es 10.
En el modo no riguroso, dicho código no informará un error, y en modo estricto, informará un error:
Object.defineProperty (myobj.prototype, 'longitud', {Writable: false, valor: '10 '}); var obj = new myobj (); obj.length = 100;Puede usar GetownPropertyDescriptor para obtener y modificar estos valores. Por ejemplo, ahora mi propiedad de longitud es de solo lectura.
Ejecutando dicho código, pero ocurrió un error:
Objeto.defineProperty (myobj.prototype, 'longitud', {valor :, witable: false,}); var descriptor = object.getOwnPropertyDescriptor (myobj.prototype, "longitud"); descriptor.writable = true; object.defineproperty (myobj.pototype, 'longitud', descriptor); No capturado typeError: no puede redefinir la propiedad: longitudEsto se debe a que el valor predeterminado de configurable es falso. Después de llamar a DefineProperty, configurable tiene la propiedad falsa, por lo que no se puede revertir. No se puede cambiar en el futuro.
Por lo tanto, debe usar configurable: verdadero y esta propiedad de objeto puede modificarse. El código completo es el siguiente:
Object.defineProperty (myobj.prototype, 'longitud', {valor :, witable: false, configurable: true}); var descriptor = object.getownpropertyDescriptor (myobj.prototype, "longitud"); descriptor.writable = true; object.defineProperty (myobj.prototype, 'longitud', descriptor); myobj.prototype.length =; var obj = new myobj (); alert (obj.length);Puede agregar una oración descriptor.configurable = false;
Significa que he modificado esta propiedad, y no puede modificarla en el futuro
Esta característica también es útil en muchos casos. Si usa métodos de llamada y aplica, se requiere la longitud del objeto para ser variable. Si el atributo de longitud del objeto es de solo lectura, se lanzará una excepción al llamar a la llamada y aplicar.
Por ejemplo, la longitud del objeto DomTokenList no se puede cambiar. Tengo un objeto dom domtokenlist,
Pero su configuración es verdadera, podemos modificarlo para que su propiedad de longitud pueda cambiarse:
Vea, este configurable es cierto, y el setter está indefinido. Vamos a escribir un método establecido para ello, ¿no está bien?
Var Descriptor = Object.getOwnPropertyDescriptor (domtokenList.prototype, 'longitud'); descriptor.set = function (valor) {this.length = value;} object.defineProperty (domtokenList.prototype, 'longitud', descriptor);Luego corre,
Se lanzó otra excepción, no captura RangeError: el tamaño máximo de la pila de llamadas superado (...)
Esto se debe a que cuando configuramos esto.
Por lo tanto, necesitamos usar Eliminar para eliminar la influencia del atributo de longitud, es decir:
var descriptor = object.getOwnPropertyDescriptor (domtokenList.prototype, 'longitud'); descriptor.set = function (valor) {delete domtokenList.prototype.length; this.length = value;} object.defineProperty (domtokenList.prototype, 'longitud', descriptor);De esta manera, DomtokenList también admite Push, Pop y otras operaciones.
Array.prototype.push.call (document.body.classlist, 'ABC')
Luego encapsular
Domtokenlist.prototype.push = function () {array.prototype.push.call (document.body.classlist, array.prototype.slice.call (argumentos));}El método array.prototype.slice.call (argumentos) se utiliza para convertir objetos de argumentos en matrices.