JavaScript 中的对象是非常重要的概念,它是用来封装相关属性和行为的数据类型,JavaScript 对象实际上是一个特殊的键值对集合,每个键值对被称为一个属性或者方法。
JavaScript 对象与 Prototype 原型用法实例分析
JavaScript 中的对象是非常重要的概念,它是用来封装相关属性和行为的数据类型,JavaScript 对象实际上是一个特殊的键值对集合,每个键值对被称为一个属性或者方法。
JavaScript 中对象的创建有很多方式,包括字面量语法、构造函数语法、Object.create() 等,本文主要讲解 JavaScript 中的 Prototype 原型用法,这种方式可以实现灵活的对象继承,方便地复用已有的代码。
JavaScript 原型
在 JavaScript 中,每个对象都有一个原型,原型是一个对象,对象可以通过原型来继承另一个对象的属性和方法,这种机制被称为原型继承,原型可以通过 __proto__
属性来访问,也可以使用 Object.getPrototypeOf() 方法来访问。
原型的作用是为对象提供一些共享的属性和方法,当对象调用一个属性或者方法时,如果该属性或方法不存在于该对象本身,则会继续在原型链中查找,直到找到该属性或方法或者到达 Object.prototype。
prototype 属性和构造函数
JavaScript 中的函数也是对象,每个函数对象都有一个 prototype
属性,该属性是一个对象,表示该函数的原型对象,当使用该函数作为构造函数创建新的实例对象时,该实例对象会从原型对象中继承属性和方法,这种机制被称为构造函数继承。
构造函数的属性和方法都存在于构造函数的原型对象中,这可以极大地减少每个实例对象所占用的内存空间,并且使得对象间共享属性和方法成为可能。
下面是一个例子,首先定义一个构造函数 Person
,然后定义 Person.prototype
对象,并在其上定义了一个 sayHello
方法,该方法用来打印字符串 "Hello, I'm ${this.name}",其中 ${this.name} 是一个占位符,表示实例对象的 name
属性值。
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function() {
console.log(`Hello, I'm ${this.name}.`);
};
然后,我们可以使用 Person
构造函数来创建实例对象,并调用 sayHello
方法,例如:
let p1 = new Person('Alice', 18);
let p2 = new Person('Bob', 20);
p1.sayHello(); // Hello, I'm Alice.
p2.sayHello(); // Hello, I'm Bob.
可以看到,两个实例对象 p1
和 p2
都可以调用 sayHello
方法,因为该方法存在于它们的原型对象 Person.prototype
中。
原型链
JavaScript 中的对象可以通过原型链来继承多个对象的属性和方法,原型链就是多个对象原型的链式链接。
例如,我们可以通过定义一个 Student
构造函数来继承 Person
的属性和方法,该构造函数的原型对象 Student.prototype
是 Person
的实例对象,这样所有通过 new Student()
创建的对象都会从 Student.prototype
继承 Person
的属性和方法。
function Student(name, age, grade) {
Person.call(this, name, age); // 调用 Person 构造函数初始化 name 和 age 属性
this.grade = grade;
}
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
Student.prototype.sayGrade = function() {
console.log(`My grade is ${this.grade}.`);
};
上述代码中,我们首先调用 Person
构造函数来初始化 name
和 age
属性,然后使用 Object.create()
方法来创建一个新对象作为 Student.prototype
,该新对象的原型对象是 Person.prototype
,这样就实现了 Student
构造函数对 Person
属性和方法的继承。
注意,我们还需要将 Student.prototype
的 constructor
属性设置为 Student
,以便后续使用 new
关键词来创建 Student
对象。
最后,我们在 Student.prototype
上定义了一个新的方法 sayGrade
,该方法用来打印字符串 "My grade is ${this.grade}",其中 ${this.grade} 是实例对象的 grade
属性值。
现在,我们可以使用 Student
构造函数来创建一个实例对象,并调用它的 sayHello
和 sayGrade
方法:
let s1 = new Student('John', 20, 'A');
s1.sayHello(); // Hello, I'm John.
s1.sayGrade(); // My grade is A.
我们可以在 Chrome 的控制台中输入 s1.__proto__
来查看该对象的原型链:
s1.__proto__ // => Student.prototype
s1.__proto__.__proto__ // => Person.prototype
s1.__proto__.__proto__.__proto__ // => Object.prototype
s1.__proto__.__proto__.__proto__.__proto__ // => null
注意到 s1.__proto__
的原型是 Student.prototype
,该对象的原型是 Person.prototype
,以此类推,最后到达 Object.prototype
,该对象是所有对象的默认原型,最后再到达 null
,表示原型链的终止。
结语
JavaScript 中的对象和原型继承是非常灵活的,它们能够让我们在开发中轻松地实现代码的复用和组合,同时还可以简化代码,提高代码的可读性和可维护性。我们需要认真学习和掌握 JavaScript 对象和原型继承的知识,以便能够在开发中灵活地使用它们。
示例一:原型链继承的缺陷
function Animal(name) {
this.name = name;
this.sleep = function() {
console.log(`${this.name} is sleeping`);
};
}
Animal.prototype.eat = function(food) {
console.log(`${this.name} is eating ${food}`);
};
function Cat(name) {
this.name = name;
}
Cat.prototype = new Animal("cat");
Cat.prototype.constructor = Cat;
let cat1 = new Cat("cat1");
let cat2 = new Cat("cat2");
cat1.eat("fish");
cat1.sleep();
cat2.eat("meat");
cat2.sleep();
console.log(cat1.sleep === cat2.sleep); //false
我们使用 Cat
构造函数来继承 Animal
的属性和方法,但是,使用 Cat.prototype = new Animal("cat");
这种方式会导致所有 Cat
实例对象共享原型对象 Animal.prototype
,如果我们通过 cat1.sleep === cat2.sleep
来比较两个实例对象的 sleep
方法,我们会发现它们不相等,原因是该方法存在于原型对象而非实例对象上,因此根据原型链继承的规则,它们实际上继承自不同的方法对象。这就是原型链继承的一个常见缺陷。
示例二:使用 Object.create() 来创建原型对象
let animal = {
name: "",
sleep: function() {
console.log(`${this.name} is sleeping`);
},
eat: function(food) {
console.log(`${this.name} is eating ${food}`);
},
};
function Cat(name) {
this.name = name;
}
Cat.prototype = Object.create(animal);
Cat.prototype.constructor = Cat;
let cat1 = new Cat("cat1");
let cat2 = new Cat("cat2");
cat1.eat("fish");
cat1.sleep();
cat2.eat("meat");
cat2.sleep();
console.log(cat1.sleep === cat2.sleep); //true
在该例子中,使用 animal
对象作为 Cat
的原型对象,可以避免多实例对象共享原型对象的问题,因为每个实例对象都拥有它自己的原型对象,而该对象是通过 Object.create()
方法来创建的,该方法会返回一个新对象,新对象的原型是参数中传入的对象。
注意,我们需要手动将 Cat.prototype
的 constructor
属性设置为 Cat
,否则会使用默认的 Object.prototype.constructor
。
本文标题为:javascript 对象 与 prototype 原型用法实例分析


基础教程推荐
- 利用Java编写个"不贪吃蛇"小游戏 2023-03-30
- 最新IDEA 2022基于JVM极致优化 IDEA启动速度的方法 2023-03-31
- Java内存模型JMM与volatile 2023-03-21
- 使用java.nio.file 库优雅的操作文件详解 2023-07-14
- SpringBoot浅析安全管理之OAuth2框架 2023-04-11
- Java中检查字符串是否以特定字符结尾 2022-12-02
- JavaWeb Servlet生命周期细枝末节处深究 2023-06-10
- springboot vue测试平台接口定义及发送请求功能实现 2022-11-15
- JavaScript实现图片倒影效果 - reflex.js 2023-08-02
- Java实现文件分片上传接口的示例代码 2023-03-15