js学习原型链

目录

什么是原型链?

如何创建原型对象?

如何将一个对象与其原型对象相关联?

如何使用原型链实现继承?

原型链查找顺序是什么?

原型链中的特殊对象是什么?

如何检查对象的原型?

如何修改对象的原型?

原型链会影响什么?

如何有效地利用原型链?


什么是原型链?

原型链是JavaScript中实现继承的机制,每一个对象都有一个原型对象(prototype),并且可以通过`__proto__`属性访问该对象的原型对象。如果原型对象也有自己的原型对象,那么就会形成一个链式结构,称为原型链。

在JavaScript中,查找一个对象的某个属性时,首先会查找该对象本身是否有该属性,如果没有则会在其原型对象上查找该属性,然后再在原型对象的原型对象上查找,依次向上查找直到找到最后一个原型对象为止。如果最后还没有找到,则会返回undefined。

通过原型链,JavaScript 实现了基于原型的继承,子类可以继承父类的属性和方法,同时也可以在自己的原型对象上增加自己的属性和方法。原型链的机制使得JavaScript在面向对象编程中非常灵活和强大。

如何创建原型对象?

在JavaScript中,可以使用构造函数或者对象字面量语法创建原型对象。

1. 使用构造函数创建原型对象

通过构造函数的方式创建原型对象,首先需要定义一个构造函数,然后使用`new`关键字创建一个实例对象,并将其赋值给构造函数的原型对象(prototype)。

function Animal(name) {
  this.name = name;
}

Animal.prototype.sayName = function() {
  console.log('My name is ' + this.name);
};

const cat = new Animal('Tom');
cat.sayName();

2. 使用对象字面量语法创建原型对象

使用对象字面量语法创建原型对象可以直接定义一个对象,并且将该对象作为原型对象,然后使用`Object.create()`方法创建一个新的对象,并将其关联到该原型对象上。

const AnimalPrototype = {
  sayName: function() {
    console.log('My name is ' + this.name);
  }
};

const cat = Object.create(AnimalPrototype);
cat.name = 'Tom';
cat.sayName();

无论是哪种方式创建的原型对象,都可以被多个对象所共享,实现代码的复用。

如何将一个对象与其原型对象相关联?

可以使用关键字`new`与构造函数,或者使用`Object.create()`方法与原型对象实现对象与原型对象相关联。

1. 使用`new`关键字与构造函数实现对象与原型对象相关联

通过`new`和构造函数创建对象时,会自动将对象与构造函数的原型对象相关联。

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.sayName = function() {
  console.log('My name is ' + this.name);
};

const john = new Person('John', 20);
john.sayName(); // 输出 "My name is John"

2. 使用`Object.create()`方法与原型对象实现对象与原型对象相关联

使用`Object.create()`方法可以创建一个新对象,并将其关联到指定的原型对象上。

const animal = {
  type: 'unknown',
  sayType: function() {
    console.log('The type is ' + this.type);
  }
};

const cat = Object.create(animal);
cat.type = 'cat';
cat.sayType(); // 输出 "The type is cat"

我们可以看到,使用`Object.create()`方法创建的对象和原型对象是平级的,它们都是对象。关联原型对象可以让对象继承原型对象的属性和方法。

如何使用原型链实现继承?

使用原型链可以很容易地实现继承。子类可以通过将父类的实例关联到子类的原型对象上来实现继承,具体实现方式如下:

1. 基于原型链继承

在子类的构造函数内创建一个父类的实例,并将其关联到子类的原型对象上。这样子类就可以从父类继承属性和方法:

// 父类
function Animal(name, age) {
  this.name = name;
  this.age = age;
}

Animal.prototype.sayName = function() {
  console.log('My name is ' + this.name);
};

// 子类
function Cat(name, age) {
  Animal.call(this, name, age); // 调用父类的构造函数
}

Cat.prototype = new Animal(); // 将父类实例关联到子类的原型对象上
Cat.prototype.constructor = Cat; // 修复 constructor

const cat = new Cat('Tom', 2);
cat.sayName(); // 输出 "My name is Tom"

2. 基于ES6的class和extends实现继承

ES6中的class和extends语法也可以用来实现继承,其背后的机制也是基于原型链的。

// 父类
class Animal {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  
  sayName() {
    console.log('My name is ' + this.name);
  }
}

// 子类
class Cat extends Animal {
  constructor(name, age) {
    super(name, age); // 调用父类的构造函数
  }
}

const cat = new Cat('Tom', 2);
cat.sayName(); // 输出 "My name is Tom"

简单来说,使用原型链继承实现继承的核心就是将子类的原型对象关联到父类实例上,以便从父类继承属性和方法。

原型链查找顺序是什么?

原型链查找顺序是从实例对象开始一直向上查找原型对象,直到查找到基础类型的Object对象(Object.prototype的原型对象为null),按照以下顺序进行查找:

1. 查找实例本身是否有该属性;
2. 如果实例本身没有该属性,则查找实例的原型对象是否有该属性;
3. 如果实例的原型对象没有该属性,则查找实例原型对象的原型对象是否有该属性;
4. 一直往上查找,直到找到基础类型Object对象,或者找到该属性。

如果一直查找到基础类型Object对象仍未找到该属性,则返回undefined。

这就是JavaScript中的原型链查找顺序,可以看出它是沿着原型对象链一步一步向上查找的。因此,如果在实例和原型中定义了同名的属性或方法,实例会覆盖原型中定义的同名属性或方法。

原型链中的特殊对象是什么?

原型链中存在一个特殊对象,它是所有对象的祖先,这个特殊对象就是Object.prototype。由于所有的对象都从Object.prototype继承来的,所以Object.prototype的原型链顶端是null,即Object.prototype的原型对象为null。

Object.prototype是一个基础类型对象,它包含一些通用的属性和方法,例如:

1. `toString()`:将对象转换为字符串;
2. `valueOf()`:返回对象的值;
3. `hasOwnProperty()`:判断对象是否具有指定的属性;
4. `isPrototypeOf()`:检查一个对象是否为另一个对象的原型。

由于所有对象都从Object.prototype继承来,所以这些通用的属性和方法可以在任意对象上调用。例如,我们可以在自定义的对象上调用`toString()`方法和`hasOwnProperty()`方法。

需要注意的是,在访问对象属性时,如果该对象自身没有该属性,会按照原型链关系向上查找,直到找到该属性或者到达原型链的顶端null。因此,在访问对象属性时需要注意继承关系。

如何检查对象的原型?

可以使用Object.setPrototypeOf()方法或者__proto__属性。

如何修改对象的原型?

可以使用Object.setPrototypeOf()方法或者__proto__属性。

原型链会影响什么?

原型链对JavaScript中的许多行为都有影响,下面列举一些常见的影响:

1. 继承:原型链让对象可以继承父对象的属性和方法。
2. 属性访问:如果对象本身没有某个属性,那么JavaScript会通过原型链在其原型对象中查找该属性。
3. 实例化:JavaScript中的构造函数的实例对象都会自动关联到原型对象上。
4. 原型方法:在原型对象上定义的方法可以被该类型的所有实例对象共享。
5. 原型属性:在原型对象上定义的属性可以被所有该类型的实例对象共享。
6. 简化对象的创建:可以通过定义一个构造函数和一个原型对象,来快速创建多个相似的对象。

总之,原型链是JavaScript中非常重要的概念之一,它决定了对象的继承关系和行为。理解原型链可以帮助我们更好地理解JavaScript中的对象、方法、属性和继承等概念。

如何有效地利用原型链?

以下是一些有效利用原型链的方式:

1. 方法或属性的共享:在原型对象上定义方法和属性可以使得所有该类型的实例对象共享这些方法和属性。这样可以节省内存,提高性能。

2. 原型继承:通过原型链实现继承是JavaScript中非常常见和重要的编程技巧。JavaScript中的继承是通过原型链来实现的,子类对象继承了父类对象的所有属性和方法,包括其原型对象上的属性和方法。在继承的过程中,我们可以通过重写原型对象上的方法来实现子类的扩展或覆盖父类的行为。

3. 原型链实现接口:在JavaScript中,通常使用原型对象来实现接口。通过在原型对象上定义一些方法和属性来实现某个接口,从而让实现该接口的对象具备相应的功能和行为。

4. 原型链深度优化:如果原型链过于深度会导致JavaScript的性能下降,因此需要在编写代码时尽可能减少原型链的深度和避免过度的嵌套。可以通过一些技巧来优化原型链,例如使用ES6中的Object.assign()方法或者使用Object.create()方法来实现对象的创建和继承等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值