对象原型
JavaScript中的每个对象都有一个原型对象,对象以其原型为模板、从原型中继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性。就这样一层一层、以此类推,这种关系就被称为了原型链。
准确地说,这些属性和方法定义在Object
的构造器函数(constructor functions
)之上的prototype
属性上,而非对象实例本身。
理解原型对象
先定义一个对象模型:
function Person(id, name, age) {
this.id = id;
// ...
}
创建一个对象并打印:
let person1 = Person(00001, "曾小晨", 102);
在 JavaScript 控制台输入 person.,就会看到,浏览器将根据这个对象的可用的成员名称进行自动补全:
在这个列表中,你可以看到定义在 person1
的原型对象、即 Person()
构造器中的成员—— name
、age
、id
。同时也有一些其他成员—— watch、valueOf 等等——这些成员定义在 Person()
构造器的原型对象、即 Object
之上。下图展示了原型链的运作机制:
如果调用了person1
的方法,浏览器会做以下事情:
- 浏览器首先检查,
person1
对象是否具有可用的valueOf()
方法。 - 如果没有,则浏览器检查
person1
对象的原型对象(即Person
)是否具有可用的valueof()
方法。 - 如果也没有,则浏览器检查
Person()
构造器的原型对象(即Object
)是否具有可用的valueOf()
方法。Object
具有这个方法,于是该方法被调用
这些继承的属性和成员都有一个前提条件:在原型对象中,把可以继承的属性和方法用Object.prototype.*
公开。
使用create()实现原型链
Object.create([object])
:如果无参,创建一个对象;如果有参,创建一个基于object
的对象,object
将是新建后的对象的原型对象。
注意
prototype
不是原型对象本身,它只是指向了一个对象,真正的原型对象本身是用__proto__
访问:
function Person(id, name, age) {
this.id = id;
this.name = name;
this.age = age;
}
Person.prototype.ddd = "A";
let person = new Person(00001, "曾小晨", 102);
let person1 = Object.create(person);
console.log(person1.prototype) // prototype 在缺省的情况下是undefined
console.log(person1.__proto__ === person) // true
使用call()实现原型链
function Person(id, name, age) {
this.id = id;
this.name = name;
this.age = age;
}
function User (email, id, name, age) {
this.email = email;
Person.call(this, id, name, age)
}
let user = new User("704729872@qq.com", 1, "曾小晨", 99);
console.log(user) // 拥有了Person的所有属性
call
可以调用构造函数、匿名函数、具名函数并指定this
。
去旅行了啊?留下足迹。OωO