var person = {
name: ['Bob', 'Smith'],
age: 32,
gender: 'male',
interests: ['music', 'skiing'],
bio: function() {
alert(this.name[0] + ' ' + this.name[1] + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.');
},
greeting: function() {
alert('Hi! I\'m ' + this.name[0] + '.');
}
};
function Person(first, last, age, gender, interests) {
this.name = {
'first': first,
'last': last
};
this.age = age;
this.gender = gender;
this.interests = interests;
this.bio = function() {
alert(this.name.first + ' ' + this.name.last + ' is ' + this.age + ' years old.' + str);
};
this.greeting = function() {
alert('Hi! I\'m ' + this.name.first + '.');
};
};
var person1 = new Object({
name : 'Chris',
age : 38,
greeting : function() {
alert('Hi! I\'m ' + this.name + '.');
}
});
var person2 = Object.create(person1);
person2是基于person1创建的, person2具有person1的属性和方法
划重点
JS实现的面向对象的继承实现与其他OO语言有着本质区别
通过原型这种机制,JavaScript 中的对象从其他对象继承功能特性
在传统的 OOP 中,首先定义“类”,此后创建对象实例时,类中定义的所有属性和方法都被复制到实例中。在 JavaScript 中并不如此复制——而是在对象实例和它的构造器之间建立一个链接(它是__proto__属性,是从构造函数的prototype属性派生的),之后通过上溯原型链,在构造器中找到这些属性和方法。
也就是说,每个对象都是构造在原型对象之上
构造函数具有prototype属性,所有会被继承的属性都定义在这里
每个对象都有__proto__属性,__proto__属性存放原型对象,新的标准中,__proto__已弃用,由Object.getPrototypeOf(obj)替代,用于得到原型对象
由构造器制造的对象,其_proto_属性指向构造器的prototype对象
是用create()方法由某对象制造的新对象,新对象的__proto__属性为原对象,即create()方法实际做的是从指定原型对象创建一个新的对象
默认情况下, 所有函数的原型属性的__proto__都是 window.Object.prototype
function Person(){};
var person = new Person();
var person1 = Object.create(person);
person.__proto__ === Person.prototype; true
person1.__proto__ === person; true;
与Java等OO语言不同原型链中的方法和属性没有被复制到其他对象——它们的访问是通过“原型链”的方式层层索引,类似子类对象调用父类中定义的方法
每个实例对象都从原型中继承了一个constructor属性,该属性指向了用于构造此实例对象的构造函数。
每一个对象的constructor属性都应当返回构造此实例的构造函数
所以 new instance.constructor(arguments) 即是使用构造函数制造了一个对象
instance.constructor.name 还能得到构造函数的名字
在讲constructor之前可能你就想对prototype做点什么了
没错,说的就是我
Person.prototype.farewell = function() {
alert(this.name.first + ' has left the building. Bye for now!');
}
那么在这条原型链下游的原型/对象都可以上溯原型链,从而调用到这个方法
即使那些对象是在Person中的prototype属性增加farewell属性之前创建的
这就是原型机制实现的OO的特点
Person.prototype.fullName = 'Bob Smith';
然而这种做法使得fullName是一个属于原型的属性,类似Java中的类变量,因此这种方法可以用来定义常属性(静态属性)
那么如何定义用于继承的属性?
在构造函数中声明属性是恰当的方法
function Person(first, last, age, gender, interests) {
fullName = this.name.first + ' ' + this.name.last;
};
构造函数中的this是动态绑定的,因此访问到的是当前对象的name
因此一种常见的对象(原型)定义模式是在构造器中定义属性,在prototype属性上定义方法
// 构造器及其属性定义
function Test(a,b,c,d) {
// 属性定义
this.a = a;
...
};
// 定义第一个方法
Test.prototype.x = function () { ... }
// 定义第二个方法
Test.prototype.y = function () { ... }
// 等等……
2019/5/26