工厂函数:
inherit(原型对象):函数返回一个新创建的对象,这个对象继承自某个原型对象
通过工厂函数创建并初始化类的实例
function range(from, to) {
var r = inherit(range.methods);
r.from = from;
r.to = to;
return r;
}
//range.methods为原型对象,这些方法为每个范围对象所继承
range.methods = {
includes: function (x) {
return this.from <=x && x < this.to
}
}
构造函数
new创建对象,构造函数初始化对象,通过this关键字获取这个对象。构造函数的prototype属性被用作新对象的原型。
//构造函数,初始化对象
function Range(from, to) {
this.from = from;
this.to = to;
}
//重写的原型对象,不包含constructor属性,在预定义的原型对象上加方法进行弥补。
Range.prototype = {
includes: function (x) {
return this.from <=x && x < this.to
}
}
//创建对象
var r = range(1,3);
r.includes(2);
每个对象拥有一个prototype属性,这个属性的值是一个对象,这个对象包含唯一一个你可美剧属性constructor。constructor属性的值是一个函数对象。
r.prototype = {constructor: function Range()}
构造函数和原型对象之间的关系,原型到构造函数的反向引用和构造函数创建的实例
检测对象的类:
1.instanceof: 对象 instanceof 构造函数
2.range.methods.isPrototypeOf®;可以判断是否存在特定的原型对象,但是不值类名
3.constructor
继承
1.原型链继承:每一个构造函数有一个原型对象,原型对象又包含一个指向构造函数的指针,而实例则包含一个原型对象的指针。
function Parent1() {
this.name = 'parent1';
this.play = [1, 2, 3]
}
function Child1() {
this.type = 'child2';
}
Child1.prototype = new Parent1();
console.log(new Child1());
var s1 = new Child1();
var s2 = new Child1();
s1.play.push(4);
console.log(s1.play, s2.play); //[1,2,3,4] [1,2,3,4]
这里的s1,s2使用的是同一个原型,因此对原型的修改会影响其他实例。
2.构造函数的继承
function Parent1() {
this.name = 'parent1';
}
Parent1.prototype.getName = function () {
return this.name;
}
function Child1() {
Parent1.call(this);
this.type = 'child'
}
let child = new Child1();
console.log(child);
console.log(child.getName);
不能继承原型方法
3.组合继承
function Parent3 () {
this.name = 'parent3';
this.play = [1,2,3];
}
Parent3.prototype.getName = function () {
return this.name;
}
function Child3() {
Parent3.call(this);
this.type = 'child3';
}
Child3.prototype = new Parent3();
var s3 = new Child3();
var s4 = new Child3();
s3.play.push(4);
console.log(s3.play, s4.play) //[1,2,3,4] [1,2,3]
console.log(s3.getName) //parent3
console.log(s4.getName) //parent3
执行了两次Parent3,解决了上述两个问题,多进行了一次性能开销。
4.原型式继承
let parent4 = {
name: "parent4",
friends: ["p1", "p2", "p3"],
getName: function() {
return this.name;
}
};
let person4 = Object.create(parent4)
person4.name = "tom";
person4.friends.push("jerry");
let Person5 = Object.create(parent4);
person5.friends.push("lucy");
console.log(person4.name)
console.log(person4.name === person4.getName())
console.log(person5.name)
console.log(person4.friends)
console.log(person5.friends)
通过Object.create()可以实现简单普通对象的继承
5.寄生式继承:
使用原型是继承获得一份目标对象的浅拷贝,然后利用这个浅拷贝的能力再进行增强,添加一些方法。
let parent5 = {
name: "parent5",
friends: ["p1", "p2", "p3"],
getName: function() {
return this.name;
}
};
function clone(original) {
let clone = Object.create(original);
clone.getFriends = function() {
return this.friends;
};
return clone;
}
let person5 = clone(parent5);
console.log(person5.getName());
console.log(person5.getFriends());
6.寄生组合式继承
function Parent6() {
this.name = 'parent6';
this.play = [1,2,3];
}
Parent6.prototype.getName = function () {
return this.name;
}
function Child6() {
Parent6.call(this);
this.friends = 'child5';
}
function clone (parent, child) {
child.prototype = Object.create(parent.ptototype);
child.prototype.constructor = child;
}
clone(Parent6, Child6);
Child6.prototype.getFriends = function () {
return this.friends;
}
let person6 = new Child6();
console.log(person6);
console.log(person6.getName());
console.log(person6.getFriends());
7.es6的extends
class Person {
constructor(name) {
this.name = name
}
// 原型方法
// 即 Person.prototype.getName = function() { }
// 下面可以简写为 getName() {...}
getName = function () {
console.log('Person:', this.name)
}
}
class Gamer extends Person {
constructor(name, age) {
// 子类中存在构造函数,则需要在使用“this”之前首先调用 super()。
super(name)
this.age = age
}
}
const asuna = new Gamer('Asuna', 20)
asuna.getName() // 成功访问到父类的方法