No JavaScript, as matrizes podem ser criadas usando o construtor da matriz, ou criado rapidamente usando [], que também é o método preferido. A matriz é um protótipo herdado do objeto e não possui um valor de retorno especial para o tipo de, ele retorna apenas 'objeto'.
No JS, pode -se dizer que tudo é um objeto, e uma matriz também é uma matriz.
Muitos objetos têm muitos métodos convenientes, como push, concat, fatia, etc. de matrizes, mas se alguns objetos não implementarem esses métodos, ainda queremos usar essas funções. Então, o que devo fazer?
1. Muitos métodos fornecem implementações muito eficientes e podemos simular suas implementações.
Por exemplo, os navegadores abaixo do IE8 não suportam o método da matriz. Para fazer o índice de suporte da matriz, podemos escrever um método para implementar o método índiceof:
(Pressione F12 para depurar com o IE Browser para selecionar a versão do navegador para IE5.)
var Arr = [,,]; if (Array.prototype.Indexof) {alert ("Seu navegador suporta indexof Method.");} else {alert ("Seu navegador não suporta ÍNDICOOF MECHOD.PTTOTPOTPOTPOTEXOFEXOFTEXOF = FUNSTTOTYPETIPO) {Array.ProType.InTyLexOxof = FUNSTOTYPTYPE) {Array.ProType.InTyTyExOxoxf = FUNSTOTYPTYPE) {Array.ProType.In); i ++) {if (this [i] == item) {return i;}} return -;}} alert (arr.indexOf ()); alert (arr.indexOf ());Claro que esse método é muito lixo. Não serei feio na implementação específica aqui e forneço uma versão de cópia no Baidu:
Se você estiver interessado, pode ver como o mecanismo V8 é implementado: https://github.com/v8/v8/blob/master/src/js/array.js
if (! Array.prototype.Indexof) {Array.prototype.IndexOF = function (elt /*, de* /) {var len = this.length >>>; var de = número (argumentos []) || ; de = (de <)? Math.CEIL (de): Math.floor (de); if (de <) de+= len; para (; de <len; de ++) {if (de este && this [de] === ELT) retornar de;} retornar -;};}2. Heritância-chamada e aplicar métodos
Se temos um objeto, não é muito problemático escrever cada objeto para implementá -lo sozinho?
Em idiomas de alto nível, podemos usar a herança para resolver o problema, como o seguinte código Java:
public class MyList <e> estende o ArrayList <E> {public void Myadd (e e) {super.add (e); System.out.println ("Add:"+E);}}Mas não há conceito de herança no JS. Podemos usar a chamada e aplicar para resolver esses problemas.
O código acima pode ser reescrito como:
var myObject = function () {} myObject.prototype.add = function () {Array.prototype.push.call (this, argumentos); // Argumentos de saída para (var i =; i <argumments.length.length; i ++) {console.log ("add:"+argumments [i];Aqui podemos ver: Embora o método Myadd seja implementado no método de herança de idiomas de alto nível, o método Myadd só pode passar um parâmetro agora. Se você deseja passar por vários parâmetros, precisa escrever outro método público vazio myadd (e [] e), ou mesmo o método public void myadd (list <e> e). O JS pode ser feito com um método, usando o objeto Argumentos para representar toda a entrada de parâmetros, o que é difícil para os idiomas de alto nível.
(PS, de fato, você pode escrever public void Myadd (e ... e) em Java. Este é um parâmetro incerto. O uso do vazio público myadd (e [] e) é o mesmo)
Chamada e aplicar métodos são usados para alterar o ponteiro deste ponteiro na função. A chamada possui apenas dois parâmetros, e a aplicação geralmente é usada após o conhecimento do número de parâmetros. O seguinte é um exemplo:
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);A referência é:
aplicar (objeto, arg1, arg2, ...)
Call (objeto, [arg1, arg2, ......])
Apenas uma "matriz" pode ser seguida pela chamada, incluindo todos os parâmetros. Aplicar é um açúcar sintático. Se você souber o número de parâmetros, será muito conveniente usar o Apply.
O objeto acima também pode ser nulo ou indefinido; portanto, esse objeto é objeto global (janela). Por exemplo, o exemplo acima será seguido:
var name = 'goo'; alert (obj1.getName.call (null)); (No modo rigoroso, como o objeto global é nulo, uma exceção será lançada: Uncathed TypeError: Não é possível ler a propriedade 'Nome' de Null)
3. Object.DefineProperty
(Nota: não use esse tipo de recurso abaixo do IE8)
Microsoft: adicione propriedades aos objetos ou modifique as propriedades das propriedades existentes.
getters, setters,
De fato, também existem funções Getters e Setter para as propriedades dos objetos no JS, mas eu pessoalmente acho que getters e setters no JS são mais parecidos com C#.
Por exemplo, o código a seguir define um getter/setter:
function myObj () {} object.DefineProperty (myobj.prototype, 'length', {get: function () {return this.length_; // Isso não pode ser comprimento.}, set: function (value) {return this.length_ = value;}});O local comentado não pode ter comprimento, caso contrário, será infinitamente recursivo.
Você também pode remover o conjunto e fazer com que a variável variável somente leitura.
Object.DefineProperty (myObj.prototype, 'length', {get: function () {return this.length_; // Isso não pode ser comprimento.}, /*Set: function (value) {return this.length_ = value;}* /}); myObj.Length = 3;Este código lançará uma exceção: Uncathed TypeError: Não é possível definir o comprimento da propriedade de #<Myobj>, que possui apenas um getter.
Para fazer com que as propriedades do objeto somente leitura, você também pode usar gravidade: false.
Object.DefineProperty (myObj.prototype, 'comprimento', {writitable: false});Redável: Falso não pode coexistir com o Get Set, caso contrário, um erro de tipo será lançado.
Configurável: pode ser excluído com a declaração de exclusão, mas a propriedade configurável parece ser válida no modo rigoroso. Esse código ainda pode ser executado no modo não estrito: (relatou um erro no modo rigoroso)
Object.DefineProperty (myObj.prototype, 'comprimento', {configurável: false}); var obj = new MyObj (); excluir obj.length;Valor: especifica o valor fixo do objeto. Valor: 10, indicando que o valor inicial desse objeto é 10.
No modo não estrito, esse código não relatará um erro e, no modo rigoroso, ele relatará um erro:
Object.DefineProperty (myObj.prototype, 'comprimento', {writíveis: false, value: '10 '}); var obj = new myObj (); obj.length = 100;Você pode usar o getOwnPropertyDescriptor para obter e modificar esses valores. Por exemplo, agora minha propriedade de comprimento é somente leitura.
Executando esse código, mas ocorreu um erro:
Object.DefineProperty (myObj.prototype, 'comprimento', {value :, winditable: false,}); var descriptor = object.GetownPropertyDescriptor (myObj.prototype, "long"); descriptor.writable = true; object.DefineProperty (myObj.Protype, '' TypeError não capturado: Não é possível redefinir a propriedade: comprimentoIsso ocorre porque o valor padrão do configurável é falso. Após a chamada do DefineProperty, o configurável possui a propriedade falsa, por isso não pode ser revertida. Não pode ser alterado no futuro.
Portanto, você deve usar configurável: true, e essa propriedade de objeto pode ser modificada. O código completo é o seguinte:
Object.DefineProperty (myObj.prototype, 'comprimento', {value :, winditable: false, configurável: true}); var descritor = object.getOwnPropertyDescriptor (myObj.prototype, "comprimento"); descriptor.writable = true; object.DefineProperty (myObj.prototype, 'comprimento', descritor); myobj.prototype.length =; var obj = new Myobj (); alert (obj.length);Você pode adicionar um descritor de frases.configurable = false;
Isso significa que eu modifiquei esta propriedade e você não pode modificá -la no futuro
Esse recurso também é útil em muitos casos. Se você usar métodos de chamada e aplicar, é necessário que o comprimento do objeto seja variável. Se o atributo de comprimento do objeto for somente leitura, uma exceção será lançada ao ligar para a chamada e aplicar.
Por exemplo, o comprimento do objeto Domtokenlist não pode ser alterado. Eu tenho um objeto dom domtokenlist,
Mas seu configurável é verdadeiro, podemos modificá -lo para que sua propriedade de comprimento possa ser alterada:
Veja, esse configurável é verdadeiro e o setter é indefinido. Vamos escrever um método definido para isso, não está bem?
var descriptor = object.GetownPropertyDescriptor (domtokenList.prototype, 'length'); descriptor.set = function (value) {this.length = value;} object.DefineProperty (domtokenlist.protype, 'length', descritor);Então correr,
Outra exceção foi lançada, RangeError não capturado: o tamanho máximo da pilha de chamadas excedido (…)
Isso ocorre porque, quando definimos isso.
Portanto, precisamos usar excluir para eliminar a influência do atributo de comprimento, ou seja::
var descriptor = object.getownPropertyDescriptor (domtokenList.prototype, 'length'); descriptor.set = function (value) {delete domntokenlist.prototype.length; this.Length = value;} object.DefineProperty (domtokenlist.prototype, 'comprimento', descritor);Dessa forma, a DomtokenList também suporta Push, Pop e outras operações.
Array.prototype.push.call (document.body.classlist, 'ABC')
Depois encapsular
Domtokenlist.prototype.push = function () {Array.prototype.push.call (document.body.classList, array.prototype.slice.call (argumentos));}O método Array.prototype.slice.call (argumentos) é usado para converter objetos de argumentos em matrizes.