Índice
prefácio
Na programação de computadores, objeto é um conceito muito importante. Ele pode nos ajudar a organizar e gerenciar melhor os dados e tornar o código mais modular e reutilizável. Um objeto pode armazenar vários pares chave-valor, cada par chave-valor representa um atributo e o atributo pode ser um valor de um tipo básico ou outro objeto. Por meio de objetos, podemos definir e chamar métodos, operar propriedades ou implementar funções específicas.
A ideia da programação orientada a objetos enfatiza a organização e o gerenciamento do código por meio de objetos e classes, facilitando sua compreensão e manutenção. De fato, decompor problemas e soluções em objetos é uma forma muito natural e intuitiva, e também é a chave para alcançar a reutilização e modularização do código.
Nos estudos seguintes, vamos entender e dominar esses conceitos mais profundamente, praticar e consolidar o conhecimento que aprendemos através de pequenos casos. Vamos embarcar em uma jornada de aprendizado juntos!
1. Reconheça o objeto
1. O que é um objeto
-
Conceito: Objeto (objeto) é uma coleção de "pares chave-valor" , representando o relacionamento de mapeamento entre atributos e valores
-
Sintaxe: k e v são separados por dois pontos , cada grupo de k:v é separado por vírgulas e vírgulas não são necessárias após o último par k:v
- Se o nome da chave de propriedade do objeto não estiver em conformidade com a convenção de nomenclatura do identificador JS, o nome da chave deverá ser colocado entre aspas
- Por exemplo:
'favorite-book':'舒克和贝塔'
há um traço no nome do atributo, que não está de acordo com a convenção de nomenclatura do identificador ]S, e o nome do atributo deve estar entre aspas
-
Acesso às propriedades do objeto
-
Você pode usar " sintaxe de ponto " para acessar o valor da chave especificada no objeto
xiaoming.name;//小明 xiaoming.age;//12 xiaoming.hobbys;//['足球',游泳','编程]
-
Se o nome do atributo não estiver em conformidade com a convenção de nomenclatura do identificador ]S, ele deve ser acessado com colchetes
xiaoming['favorite-book'];//舒克和贝塔
-
Se o nome do atributo for armazenado como uma variável, ele deve estar entre colchetes
var obj = { a:1, b:2, C:3 }; //属性名用变量存储 var key ='b'; console.log(obj.key); //undefined console.log(obj[key]);//2
-
-
mudança de propriedade
- Use diretamente o operador de atribuição para reatribuir uma propriedade para alterar a propriedade
var obj ={ a:10 } obj.a = 30; //将obj里a的值改成了30 ob].a++; // a = 31
- Use diretamente o operador de atribuição para reatribuir uma propriedade para alterar a propriedade
-
criação de atributos
- Se o próprio objeto não tiver um valor de propriedade, a propriedade será criada quando a sintaxe de ponto for usada para atribuir um valor
var obj ={ a:10 }; obj.b = 40; //在obj对象中创建了b:40这个键值对
- Se o próprio objeto não tiver um valor de propriedade, a propriedade será criada quando a sintaxe de ponto for usada para atribuir um valor
-
exclusão de propriedade
-
Se você deseja excluir uma propriedade de um objeto, você precisa usar o operador delete
var obj = { a:1, b:2 }; delete obj.a;
-
2. Métodos de objeto
-
Se o valor de uma propriedade for uma função , também é chamado de " método " do objeto
varxiaoming = { sayHello:function(){ //sayHello方法 console.log('你好,我是小明,今年12岁,我是个男生'); } }
-
Chamando uma função com o método dot
xiaoming.sayHello();
-
O método também é uma função , mas o método é o "atributo de função" do objeto e precisa ser chamado pelo objeto
3. Travessia de objeto
- Com o loop for ... in ... , você pode iterar sobre cada chave do objeto
4. Clonagem profunda e superficial de objetos
- Quando o objeto é um valor de tipo de referência
- Um objeto não pode ser
var obj1 = obj2
clonado usando uma sintaxe como esta - Ao usar == ou === para comparar objetos, a comparação é se eles são o mesmo objeto na memória , não se os valores de comparação são os mesmos
- Um objeto não pode ser
- clone raso
- A clonagem superficial de objetos pode ser obtida usando o ciclo for ...in...
- clone profundo
-
Semelhante ao tipo de array, a clonagem profunda de objetos requer o uso de recursão
var obj1 = { a:1, b:2, c:[33,44,{ m:55, n:66, p:[77,88] }] }; // 定义一个深克隆函数 function deepClone(o){ // 判断o是对象还是数组,必须先判断是不是数组,因为数组的类型也是对象 if(Array.isArray(o)){ //数组 var result = []; for(var i=0;i < o.length;i++){ result.push(deepClone(o[i])); } }else if(typeof o == 'object'){ // 对象 var result = { }; for (var k in o){ result[k] = deepClone(o[k]) } }else{ //基本类型值 var result = o; } return result; } var obj2 = deepClone(obj1); console.log(obj2); // 测试一下 console.log(obj1 === obj2); //false obj1.c.push(99); console.log(obj2); //obj2是不变的,因为没有'藕断丝连'的现象
-
2. Conheça o contexto da função
-
O contexto da função ( esta palavra-chave) é determinado pelo método de chamada ; a mesma função é chamada de formas diferentes e o contexto da função é diferente
var xiaoming = { nickname:小明, age:12, sayHello = function (){ console..log('我是'+this.nickname+',我'+this.age+'岁了); } };
-
Cenário 1: A função é chamada pelo objeto ponto, e este na função refere-se ao objeto pontilhado
xiaoming.sayHello();
-
Caso 2: Os parênteses chamam diretamente a função, e isso na função refere-se ao objeto janela
var sayHello = xiaoming.sayHello; sayHello();
-
-
função é a estratégia " contexto de tempo de execução "
-
Se a função não for chamada, o contexto da função não pode ser determinado
1. Regras de contexto para funções★
-
Regra①
- O objeto ponto chama sua função de método, então o contexto da função é o objeto pontilhado
对象.方法();
-
Regra ②
- Os parênteses chamam a função diretamente e o contexto da função é o objeto da janela
函数();
-
Regra ③
- A matriz (objeto semelhante a uma matriz) enumera a função a ser chamada e o contexto é esta matriz (objeto semelhante a uma matriz)
- O que é um objeto semelhante a uma matriz: um objeto cujo nome de chave é uma sequência de números naturais (começando em 0) e possui um atributo de comprimento
- O objeto de argumentos é o objeto semelhante a uma matriz mais comum, que é a lista de parâmetros real da função
数组[下标]();
- A matriz (objeto semelhante a uma matriz) enumera a função a ser chamada e o contexto é esta matriz (objeto semelhante a uma matriz)
-
Regra ④
-
Função no IIFE, o contexto é o objeto da janela
(function(){ })();
-
-
Regra ⑤
- O temporizador e o retardador chamam a função, o contexto é o objeto da janela
setInterval(函数,时间);
setTimeout(函数,时间);
-
Regra ⑥
- O contexto do manipulador de eventos é o elemento DOM ao qual o evento está vinculado
DOM元素.onclick=function(){ }
- O contexto do manipulador de eventos é o elemento DOM ao qual o evento está vinculado
2. ligue e candidate-se ★
- call e apply podem especificar o contexto da função
函数.ca11(上下文);
Para listar parâmetros com vírgulas函数.apply(上下文);
Para escrever os parâmetros no array
3. Construtor
1. Chame a função com o novo operador
-
"Quatro Passos"
- 1) Um objeto em branco é criado automaticamente no corpo da função
- 2) O contexto (this) da função apontará para este objeto
- 3) A instrução no corpo da função será executada
- 4) A função retornará automaticamente o objeto de contexto, mesmo que a função não tenha uma instrução de retorno
2. Classes e instâncias
3. Construtores e 'classes'
-
Java, C++, etc. são linguagens " orientadas a objetos " (orientadas a objetos)
-
JavaScript é uma linguagem " baseada em objeto"
-
O construtor em JavaScript pode ser comparado à "classe" na linguagem OO . O método de escrita é realmente semelhante, mas ainda é fundamentalmente diferente da linguagem OO real.
4. Protótipo e cadeia de protótipos
1. Protótipo e busca em cadeia de protótipos★
- Qualquer função tem um atributo protótipo , e protótipo significa "protótipo"
- O valor da propriedade protótipo é um objeto, que por padrão tem a propriedade construtor apontando de volta para a função
- O atributo protótipo para funções comuns é inútil, mas o atributo protótipo para construtores é muito útil
- A propriedade protótipo de um construtor é o protótipo de sua instância
console.log(xiaoming.__proto__ === People.prototype); //true
- A propriedade protótipo de um construtor é o protótipo de sua instância
- pesquisa de cadeia de protótipo
- JavaScript estipula que uma instância pode acessar as propriedades e métodos de seu protótipo
- método hasOwnProperty()
- Pode verificar se o objeto realmente "possui" uma propriedade ou método
- no operador
- Você só pode verificar se uma determinada propriedade ou método pode ser acessado pelo objeto, você não pode verificar se é sua própria propriedade ou método
2. Adicione métodos no protótipo
- Desvantagens de adicionar métodos diretamente às instâncias: cada instância e a função de método de cada instância são funções diferentes na memória, resultando em desperdício de memória
- Solução: Adicione o método ao protótipo
3. O fim da cadeia do protótipo
- O fim da cadeia de protótipos de todas as coisas - Object.prototype
-
exemplo de código
function People(){ } var xiaoming = new People(); console.log(xiaoming.__proto__.__proto__ === Object.prototype); //true console.log(Object.prototype.__proto__); //null console.log(Object.prototype.hasOwnProperty('hasOwnProperty')); //true
-
cadeia de protótipo do array
var arr = [22,33,4,555];
console.log(arr.__proto__ === Array.prototype); //true
console.log(arr.__proto__ .__proto__=== Object.prototype); //true
console.log(Array.prototype.hasOwnProperty('push')); //true
4. Herança★
-
A herança descreve o relacionamento "é um tipo de" entre duas classes . Por exemplo, um aluno "é um tipo de" pessoa, portanto, um relacionamento de herança é formado entre um ser humano e uma classe de aluno
-
Pessoas é a " classe pai " (ou "superclasse", "classe base"); Aluno é a " subclasse " (ou "classe derivada")
-
A subclasse enriquece a classe pai, tornando a descrição da classe mais específica e detalhada
-
exemplo
- Herança através da cadeia de protótipos
- Deixe o protótipo do construtor da subclasse apontar para uma instância da classe pai:
Student.prototype = new People();
- Deixe o protótipo do construtor da subclasse apontar para uma instância da classe pai:
//父类:人类
function People(name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
}
People.prototype.sayHello = function (){
console.log('你好,我是'+this.name +'我今年'+this.age+'岁了');
}
People.prototype.sleep = function (){
console.log(this.nam+'开始睡觉,zzzz');
}
// 子类:学生
function Student(name,age,sex,school,studentNumber){
this.name = name;
this.age = age;
this.sex = sex;
this.school = school;
this.studentNumber = studentNumber;
}
//关键语句,实现继承
Student.prototype = new People();
Student.prototype.study = function (){
console.log(this.name + '正在学习');
}
Student.prototype.exam = function (){
console.log(this.name+'正在考试,加油!');
}
//实例化
var hanmeimei = new Student('韩梅梅',12,'女','CSDN大学',123456);
hanmeimei.study();
hanmeimei.sayHello();
Cinco, subindo para orientação a objetos
- A essência da orientação a objetos: defina classes diferentes, deixe as instâncias da classe funcionarem
- Vantagens da orientação a objetos: escrita de programa mais clara, estrutura de código mais compacta, código mais robusto e manutenção mais fácil
- Ocasiões em que a orientação a objetos é frequentemente usada: ocasiões que requerem encapsulamento e reutilização (pensamento de componentes)
1. Caixa pequena de semáforos
-
Usando a programação orientada a objetos, você pode resolver o problema de um grande número de semáforos conflitantes com o pensamento " componente "
-
Programação orientada a objetos, o mais importante é escrever classes
-
classe TrafficLight
- Atributos: própria cor atual, próprio elemento DOM dom
- Método: inicializar init(), mudar a cor changeColor(), ligar o evento bindEvent()
-
Exemplo de código:
#box img{ width: 80px ; }
<div id="box" ></div>
//定义红绿灯类,构造函数 function TrafficLight(){ //颜色属性,一开始都是红色 //红色1,黄色2,绿色3 this.color = 1; //调用自己的初始化方法 this.init(); //绑定监听 this.bindEvent(); } //初始化方法 TrafficLight.prototype.init = function (){ // alert('我是init方法'); //创建自己的DOM this.dom = document.createElement('img'); this.dom.src = this.color+'.jpg'; box.appendChild(this.dom); } // 绑定监听 TrafficLight.prototype.bindEvent = function (){ //备份上下文,这里的this指的是JS实例 var self = this; //当自己的dom被点击时 this.dom.onclick = function (){ // 当被点击时,调用自己的changeColor方法 self.changeColor(); }; } // 改变颜色 TrafficLight.prototype.changeColor = function (){ // 改变自己的color属性,从而有一种"自治"的感觉,自己管理自己不干扰别的红绿灯 this.color++; if(this.color == 4){ this.color = 1; } // 光color属性变化没用,还要更改自己的dom中src属性,才能更换图片 this.dom.src = this.color+'.jpg'; }; // 得到盒子 var box = document.getElementById('box'); // 实例化100个 var count = 100; // 当count-- 为0的时候,判断为false,跳出循环 while(count--){ new TrafficLight(); }
2. Pequena caixa de bola colorida
-
Propriedades da classe Boll
-
Métodos da classe Boll
- método de inicialização init()
- método de atualização update()
-
Realize a animação de várias bolinhas pequenas
- Coloque cada instância de bola na mesma matriz
- [{instância da bola},{instância da bola},{instância da bola},{instância da bola}]
- Você só precisa usar um cronômetro para percorrer cada bola em cada quadro e chamar seu método de atualização
- Coloque cada instância de bola na mesma matriz
-
Exemplo de código:
body{ background-color: black; } .ball{ position: absolute; border-radius: 50%; }
//小球类 function Ball(x,y){ //属性x,y表示的是圆心的坐标 this.x = x; this.y = y; //透明的 this.opacity = 1; do{ // 这个小球的x增量和y的增量 this.dX = parseInt(Math.random()*20)-10; this.dY = parseInt(Math.random()*20)-10; }while(this.dX === 0 || this.dY === 0) // 小球的背景颜色 this.color = colorArr[parseInt(Math.random()*colorArr.length)]; // 小球半径 this.r = 20; // 初始化 this.init(); // 把自己推入数组,注意:这里的this不是类本身,而是实例 ballArr.push(this); } Ball.prototype.init = function (){ //创建自己的dom this.dom = document.createElement('div'); this.dom.className = 'ball'; this.dom.style.width = this.r *2 +'px'; this.dom.style.height = this.r *2 +'px'; this.dom.style.left = this.x - this.r+'px'; this.dom.style.top = this.y - this.r+'px'; this.dom.style.backgroundColor = this.color; //上树 document.body.appendChild(this.dom); } // 更新 Ball.prototype.update = function (){ // 位置改变 this.x += this.dX; this.y -= this.dY; // 半径改变 this.r += 0.2; // 透明度改变 this.opacity -= 0.05; this.dom.style.width = this.r *2 +'px'; this.dom.style.height = this.r *2 +'px'; this.dom.style.left = this.x - this.r+'px'; this.dom.style.top = this.y - this.r+'px'; this.dom.style.opacity = this.opacity; // 当透明度小于0,就需要从数组中删除自己,DOM元素也要删除自己 if(this.opacity<0){ //从数组中删除自己 for (var i = 0; i<ballArr.length;i++){ if(ballArr[i] == this){ ballArr.splice(i,1); } //还要删除自己的dom document.body.removeChild(this.dom); } } }; // 把所有的小球实例都放到一个数组中 var ballArr = []; // 初始颜色数组 var colorArr = ['#66CCCC','#CCFFCC','#FF99CC','#FF6666','#CC3399','#ff6600'] // 定时器,负责更新所有的小球实例 setInterval(function (){ //遍历数组 ,调用update方法 for(var i= 0;i<ballArr.length;i++){ ballArr[i].update(); } },20); // 鼠标指针的监听 document.onmousemove = function (e){ //得到鼠标指针的位置 var x = e.clientX; var y = e.clientY; new Ball(x,y); }
Six, objetos internos do JS
1. Embalagem
- Instâncias de Number(), String() e Boolean() são todos tipos de objeto e suas propriedades Primitivevalue armazenam seus próprios valores
- O valor do tipo básico de new pode normalmente participar da operação
- O objetivo das classes wrapper é permitir que valores básicos de tipo obtenham métodos do protótipo de seus construtores
2. Objeto matemático ★
-
Potência e raiz quadrada: Math.pow(), Math.sqrt()
-
Arredondamento para cima e para baixo: Math.ceil(), Math.floor()
-
Método Math.round(): arredondamento
- arredondar para duas casas decimais
- arredondar para duas casas decimais
-
Math.max(): Obtém o valor máximo da lista de parâmetros
- Use Math.max() para encontrar o valor máximo de uma matriz
-
Math.max() exige que o parâmetro seja "listado", não um array
-
Com o método apply, ele pode especificar o contexto da função e passar "valores dispersos" como parâmetros da função na forma de um array
var arr = [3,6,9,2]; var max = Math.max.apply(null,arr); console.log(max); // 9
-
- Use Math.max() para encontrar o valor máximo de uma matriz
-
Math.min(): Obtém o valor mínimo da lista de parâmetros
-
Math.random(): Obter um decimal entre 0 e 1
- Para obter um número inteiro no intervalo [a,b], você pode usar esta fórmula:
- parseInt(Math.random()*(ba +1))+a
- Para obter um número inteiro no intervalo [a,b], você pode usar esta fórmula:
3. Objeto de data ★
- Use new Date() para obter o objeto de data da hora atual, que é um valor de tipo de objeto
- Use new Date(2023,6,26) para obter o objeto de data da data especificada,
- Observe que o segundo parâmetro representa o mês, começando em 0 e 6 representa julho
- Também pode ser escrito como new Date('2023-07-26')
- Use new Date(2023,6,26) para obter o objeto de data da data especificada,
- Métodos comuns do objeto de data
- carimbo de data/hora
-
O registro de data e hora representa o número de milissegundos a partir de um determinado momento em 1º de janeiro de 1970 às zero horas
-
O objeto de data pode ser transformado em um timestamp pelo método getTime() ou pela função Date.parse()
-
Ao escrever uma nova data (carimbo de data/hora), o carimbo de data/hora pode ser alterado para um objeto de data
-
7. Herança e construtores internos [Expandir]
-
construtor embutido
- JavaScript tem muitos construtores embutidos . Por exemplo, Array é o construtor do tipo array, Function é o construtor do tipo de função e Object é o construtor do tipo de objeto.
- O construtor embutido é muito útil. Todos os métodos deste tipo são definidos no protótipo de seu construtor embutido . Podemos adicionar novos métodos a este objeto para expandir a funcionalidade de um determinado tipo
- Number\String\Boollearn é uma classe wrapper para três tipos básicos de valores. Chamá-los com new pode gerar versões de "objeto" de valores de tipo básico
-
Relações Construtoras Integradas
- Qualquer função pode ser considerada como Função "nova", incluindo Objeto
- Qualquer função pode ser considerada como Função "nova", incluindo Objeto
-
Com construtores (também conhecidos como "objetos falsos" ou "herança clássica")
- Vantagens: Resolve o problema causado pelo valor do tipo de referência contido no protótipo e o problema deselegante do construtor da subclasse
- Princípio: Chame o construtor da superclasse dentro do construtor da subclasse , mas preste atenção ao usar call() para vincular o contexto
function People(name,sex,age){ this.name = name; this.sex = sex; this.age = age; this.arr = [22,33,44]; } function Student(name,sex,age,school,sid){ People.call(this,name,sex,age); // 借助构造函数 this.school = school; this.sid = sid; } var xiaoming = new Student('小明','男',12,'CSDN学校',123455); console.log(xiaoming); </script>
-
Herança de composição (mais comumente usada)
- Princípio: A tecnologia de pegar emprestado a cadeia de protótipos e pegar emprestado o construtor é combinada, também chamada de herança pseudoclássica
- Desvantagens: Em qualquer caso, o construtor da superclasse será chamado duas vezes, uma ao criar o protótipo da subclasse e outra dentro do construtor da subclasse
//父类 function People(name,sex,age){ this.name = name; this.sex = sex; this.age = age; } People.prototype.sayHello = function (){ console.log('你好,我是'+this.name+'今年'+this.age+'岁了'); } People.prototype.sleep = function (){ console.log(this.name+'正在睡觉'); } //子类 function Student(name,sex,age,school,sid){ //借助构造函数 People.call(this,name,sex,age); this.school = school; this.sid = sid; } //实现继承:借助原型链 Student.prototype = new People(); Student.prototype.exam = function (){ console.log(this.name + '正在考试') } Student.prototype.sayHello = function (){ console.log('敬礼!你好,我是'+this.name+'今年'+this.age+'岁了'+this.school+'的学生'); } var xiaoming = new Student('小明','男',12,'CSDN学校',123455); console.log(xiaoming); xiaoming.sayHello(); xiaoming.sleep(); xiaoming.exam();
-
herança prototípica
- Conheça Object.creat()
- O IE9+ passa a oferecer suporte ao método Object.create(), que pode criar um novo objeto com base no objeto especificado como um protótipo , sem recorrer ao construtor
- Exemplo:
var obj2 = Object.create(obj1);
- Conceito: No caso em que não há necessidade de criar um construtor, mas apenas se deseja que o novo objeto seja "semelhante" ao objeto existente, pode-se usar Object.create(), que é chamado de herança prototípica
- Conheça Object.creat()
-
herança parasitária
- Escreva uma função que receba um parâmetro o, retorne um novo objeto p com o como protótipo e adicione um novo método pré-fabricado a p
- A herança parasitária é escrever uma função que pode " aprimorar o objeto ". Desde que o objeto seja passado para esta função, a função criará um novo objeto com base neste objeto e atribuirá um novo método predefinido ao novo objeto.
- A herança parasitária também é um padrão útil nos casos em que os objetos são considerados principalmente em vez de tipos e construtores personalizados
- Desvantagens: Usar herança parasitária para adicionar funções a objetos reduzirá a eficiência devido à incapacidade de obter a reutilização da função, ou seja, "o método não está escrito no protótipo "
- Escreva uma função que receba um parâmetro o, retorne um novo objeto p com o como protótipo e adicione um novo método pré-fabricado a p
-
herança composicional parasitária
- Herdar propriedades emprestando construtores
- Herança de métodos por meio de uma forma híbrida da cadeia de protótipos
- Ideia básica: Não é necessário chamar o construtor do supertipo para especificar o protótipo do subtipo, basta uma cópia do protótipo do supertipo. Essencialmente, use a herança parasitária para herdar o protótipo do supertipo e, em seguida, atribuir o resultado ao protótipo do subtipo
-
instância do operador
- O operador instanceof é usado para detectar "se um objeto é uma instância de uma determinada classe", como: xiaoming instanceof Student
- Mecanismo subjacente: Verifique se o atributo Student.prototype está na cadeia de protótipos de xiaoming (quantas camadas estão bem, contanto que esteja lá)