JavaScript不区分类和实例的概念,而是通过 原型(prototype)来实现面向对象编程。
现在有一个现成的 Student
对象,我们根据它来“创建”一个 xiaoming
对象,使其拥有 Student
的属性和方法:
var Student = {
name: 'Robot',
height: 1.2,
run: function () {
console.log(this.name + ' is running...');
}
};
var xiaoming = {
name: '小明'
};
xiaoming.__proto__ = Student;
注意最后一行代码把 xiaoming
的原型指向了对象 Student
,看上去 xiaoming
仿佛是从 Student
继承下来的:
xiaoming.name; // "小明"
xiaoming.height; // 1.2
xiaoming.run(); // 小明 is running...
xiaoming
有自己的 name
属性,但并没有定义 run()
方法。不过,由于小明是从 Student
继承而来,因为 Student
有 run()
方法,所以 xiaoming
也可以调用:
JavaScript 的原型链和 Java 的 Class 区别就在,它没有 “Class” 的概念,所有对象都是实例,所谓 继承关系不过是把一个对象的原型指向另一个对象而已。
如果你把 xiaoming
的原型指向其他对象:
var Bird = {
fly: function () {
console.log(this.name + ' is flying...');
}
};
xiaoming.__proto__ = Bird;
现在 xiaoming
已经无法 run()
了:
xiaoming.run(); // 报错
xiaoming.fly(); // 小明 is flying...
在 JavaScrip 代码运行时期,你可以把 xiaoming
从 Student
变成 Bird
,或者变成任何对象。
请注意,上述代码仅用于演示目的。在编写 JavaScript 代码时,不要直接用 obj.__proto__
去改变一个对象的原型,并且,低版本的 IE 也无法使用 __proto__
。
Object.create()
方法可以传入一个原型对象,并创建一个基于该原型的新对象,但是新对象什么属性都没有,因此,我们可以编写一个函数来创建 xiaoming
:
// 原型对象:
var Student = {
name: 'Robot',
height: 1.2,
run: function () {
console.log(this.name + ' is running...');
}
};
function createStudent(name) {
// 基于Student原型创建一个新对象:
var s = Object.create(Student);
// 初始化新对象:
s.name = name;
return s;
}
var xiaoming = createStudent('小明');
xiaoming.run(); // 小明 is running...
xiaoming.__proto__ === Student; // true