构造函数
JS声明的函数都可以作为构造函数
原型对象
当声明一个函数后,浏览器自动会创建一个对象(包括构造函数),这个对象是原型对象
function a() {}
var obj = new a();
console.dir(obj);
console.log(obj.constructor)
console.dir(Object);
prototype
每个函数都有一个 prototype 属性,也叫显性原型
每一个JavaScript对象(null除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型"继承"属性。
function Person(name) {
this.name = name;
}
console.log(Person.prototype);
proto
proto是隐性原型,每一个JavaScript对象(除了 null )都具有的一个属性,叫proto,这个属性会指向该对象的原型
function Person(name) {
this.name = name;
}
var p = new Person('原型');
console.log(Person.prototype);
console.log(p.__proto__ == Person.prototype);//true
constructor
每个原型都有一个 constructor 属性指向关联的构造函数
继承
1.原型链继承
// 第一种:原型链继承
function son() {
this.name = 'Im son';
}
function father() {
this.name = 'Im father';
}
son.prototype = new father(); //实例化父级后的对象作为子类的原型(这一步非常重要)
// son.prototype = father.prototype; //这样写虽然说instanceof也为ture,但是没意义
son.prototype.constructor = son; //给子类的原型增加构造函数,使其成为完整的原型对象
console.dir(new son instanceof son); //true
console.dir(new son instanceof father); //true
2.借用父级构造函数继承
// 第二种:借用父级构造函数继承
function Person(name, age) {
this.name = name
this.age = age
this.action; //undefined
}
Person.prototype.action = function() {
console.log('my name is', this.name);
}
function student(name, age) {
Person.call(this, name, age);
}
var tom = new student('Tom', 12);
console.log(tom);
console.log(tom instanceof student); //false
缺点: 方法都定义在构造函数中,函数的复用就就无从谈起,在超类型中定义的方法,对子类而言是不可见的,结果导致所有类型只能使用构造函数模式(也就是说无法重用方法)
3.
寄生组合式
//父类
function People(name, age) {
this.name = name || 'harley'
this.age = age || 24
}
//父类方法
People.prototype.action = function() {
return this.name + this.age + 'sey hi'
}
//子类
function Woman(name, age) {
//继承父类属性
People.call(this, name, age)
}
//继承父类方法
(function() {
// 创建空类
let Super = function() {};
Super.prototype = People.prototype;
//父类的实例作为子类的原型
Woman.prototype = new Super();
})();
//修复构造函数指向问题
Woman.prototype.constructor = Woman;
let my = new Woman();
console.log(my instanceof People); //true