JS原型
1.什么是函数对象?
function F1(){};
var F2 = function(){};
var F3 = new function (){};
//F1,F2,F3均为函数对象,实质都是通过new function()创建而来;
2.构造函数
function Person(name,age){
this.name = name;
this.age = age;
this,SayName = function(){
alert(this.name);
}
}
var person1 = new Person();
var person2 = new Person();
上述例子中,Person为构造函数,而person1和person2为构造函数的两个实例,而实例会自身带有constructor(构造函数)属性,该属性是一个指针,指向构造函数Person.
person.constructor == Person //true
3.原型对象
每个函数对象对会有一个prototype属性(普通对象没有这个属性),这个属性指向函数的原型对象。
function Person(name,age){
this.name = name;
this.age = age;
this,SayName = function(){
alert(this.name);
}
}
var person1 = new Person();
var person2 = new Person();
实际上换一种写法更加清楚:
Person.prototype = {
name:"wang";
age:28;
SayName:function(){};
}
原型对象就是Person.prototype.
而原型对象会有一个construtor属性,该属性指向构造函数。
Person.prototype.construtor == Person // true
3.__proto__属性
JS在创建对象是对会有一个叫做__proto__的内置属性,用于指向创建他的构造函数的原型对象。
例如上述例子中,实例proson1有__proto__属性,而创建它的构造函数为Person,Person构造函数的原型对象就是Person.prototype.
person1.__proto__ == Person.prototype //true
4.原型链
单理解就是原型组成的链,对象的__proto__它的是原型,而原型也是一个对象,也有__proto__属性,原型的__proto__又是原型的原型,就这样可以一直通过__proto__想上找,这就是原型链,当向上找找到Object的原型的时候,这条原型链就算到头了。
Grand.prototype.LastName = "JS";
function Grand (){
}
var grand = new Grand();
Father.prototype = grand;
function Father(){
this.name = "CSS";
}
var father = new Father;
Son.prototype = father;
function Son(){
}
var son = new Son();
console.log(son.LastName); //"JS"
console.log(son.name); //"CSS"
JS继承
1.传统形式 --(原型链)
(缺点:过多继承了没有用的东西)
Grand.prototype.LastName = "JS";
function Grand (){
}
var grand = new Grand();
Father.prototype = grand;
function Father(){
this.name = "CSS";
}
var father = new Father;
Son.prototype = father;
function Son(){
}
var son = new Son();
console.log(son.LastName); //"JS"
console.log(son.name); //"CSS"
缺点也就是说当我只想继承grand的LastName属性的时候,也会同时继承father的name属性。
2.借用构造函数
(缺点:不能继承借用构造函数得原型;每次构造函数都要做走一个函数)
//借用构造函数继承
function Person (name,age,sex){
this.name = name;
this.age = age;
this.sex = sex;
}
function Student(name,age,sex,grade){
Person.call(this,name,age,sex);
this.grade = grade;
}
var student = new Student("xiaowang",28,"male","90");
student不能借用构造函数得原型。并且在调用student函数时,会访问到person函数。
3.共享原型
(缺点;不能随意改动自己的原型)
//共享原型
Father.prototype.lastname = "KANG";
function Father (){
}
function Son(){
}
Son.prototype = Father.prototype;
var son = new Son();
var father = new Father();
//封装方法
function inherit(Target,Origin){
Target.prototype = Origin.prototype;
}
//引用:必须在继承之前改动原型:inherit(Son,Father)
缺点就是:共享原型中 Son.prototype 和 Father.prototype 指向是同一个空间,改变Son的一个属性,Father的也会跟着改变。
4.圣杯模式
(比较完美)
//圣杯模式
function inherit(Target,Origin){
function F(){};
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constuctor = Target;
}
Father.prototype.LastName = "Deng";
function Father(){
}
function Son(){
}
inherit(Son,Father);
var son = new Son();
var father = new Father();