- 在JavaScript中,每个对象都有一个原型对象,原型对象也是一个对象,它包含了对象的共享属性和方法。每个构造函数(除了箭头函数)都有一个prototype属性,该属性指向构造函数的原型对象。
- 当我们使用构造函数创建一个新对象时,该对象会继承构造函数的原型对象中的属性和方法,这种继承关系就构成了原型链。
- 构造函数通过原型对象实现了对象之间的共享属性和方法,构造函数的实例通过原型链继承了构造函数的原型对象的属性和方法。这种原型链的机制使得JavaScript中的对象可以实现一种灵活的继承和共享特性的方式。
构造函数
构造函数调用的时候,必须通过一个 new 关键字来调用;我们一般不直接使用构造函数,而是使用构造函数创建出来的实例对象,构造函数是 js 面向对象的一个重要组成部分。
使用构造函数就可以快速创建具有一些相似的属性和方法的对象,减少重复代码实现代码复用
class Person {
constructor(name,age) {
this.name = name;
this.age = age;
}
}
const P1 = new Person('小a',18);
const P2 = new Person('小b',19);
const P3 = new Person('小c',20);
console.log(P1,P2,P3);
//Person {name: '小a', age: 18}
//Person {name: '小b', age: 19}
//Person {name: '小c', age: 20}
除了 null 原型对象之外,任何对象都会在其 [[Prototype]]
上有一个 constructor
属性指向构造函数。使用字面量创建的对象也会有一个指向该对象构造函数类型的 constructor
属性,例如,数组字面量创建的 Array
对象和对象字面量创建的普通对象。
原型对象和原型链
function MyObject(city) {
this.city=city;
this.greet=function () {
console.log(`Hello,${this.city}!`);
}
}
var myobj=new MyObject("world");
myobj.greet(); // Hello,world!
这里有一个对象,它具有数据属性 city
和方法 greet()
,如果你在控制台中输入对象的名称,然后跟随一个小数点(如同 myObject.
),你会看到,除了 city
和 greet
外,还有很多其他属性!
访问其中一个:
myObject.toString(); // "[object Object]"
也可以在MyObject的原型上添加属性和方法
MyObject.prototype.name = `小明`
MyObject.prototype.sayHello = function() {
console.log(`Hello,My name is ${this.name}`)
}
myobj.sayHello() // Hello,My name is 小明
每个构造函数都有一个 prototype
属性,即原型对象,通过实例对象的__proto__
属性也可访问原型对象;而原型对象本质也是一个对象,是对象就有自己的原型对象,最终形成的链状的结构称为原型链。原型链终止于拥有 null
作为其原型的对象上。
当你试图访问一个对象的属性时:如果在对象本身中找不到该属性,就会在原型中搜索该属性。如果仍然找不到该属性,那么就搜索原型的原型,以此类推,直到找到该属性,或者到达链的末端,在这种情况下,返回 undefined
。
myObject
的原型是什么?可以使用 Object.getPrototypeOf()
函数查看
Object.getPrototypeOf(myObject); // Object { }
有个对象叫 Object.prototype
,它是最基础的原型,所有对象默认都拥有它。Object.prototype
的原型是 null
,所以它位于原型链的终点:
一个对象的原型并不总是 Object.prototype
,如 Date
对象的原型是 Date.prototype
对象,Date.prototype
的原型是 Object.prototype
。