上期题目解答
1.请输出下面构造该对象的构造函数的名
function A(){};
function B(){};
function CreateObj(){
var n = Math.random();
if(n < 0.5){
return new A();
}else{
return new B();
}
}
var obj = CreateObj();
console.log(obj.__proto__.constructor.name)
//先找到obj的构造函数的原型,原型里有constructor属性指向构造函数本身
2.请问下面三个会输出什么,为什么
function A(){};
function B(a){
this.a = a;
}
function C(a){
if(a){
this.a = a;
}
}
A.prototype.a = 1;
B.prototype.a = 1;
C.prototype.a = 1;
console.log(new A().a);//new A()上没有a属性,就找A.prototype.a
console.log(new B().a);//new B()上有a属性,但未传参,所以值为undefined
console.log(new C(2).a);//new C()上有a属性,a=2,所以值为2
3.下面代码会输出什么(根据下图理解)
function A(){};
A.prototype.say = function(){};
var a1 = new A();
var a2 = new A();
console.log(a1.say === a2.say);//都是通过构造函数构造,为true
console.log (A.prototype.constructor );//指向它本身。function A(){}
console.log(A.prototype === Function.prototype);
//A由Function构造,A.__proto__指向Function.prototype,所以false
console.log(A.__proto__ === Function.prototype);
//Function的prototype和__proto__以及Object.__proto__都指向Function原型,所以true
console.log(A.__proto__ === Function.__proto__);//true
console.log(a1.__proto__ === a2.__proto__);//true
console.log(a1.__proto__ === A.__proto__);//父子关系,false
console.log(Function.__proto__ === Object.__proto__);
//Object.__proto__也指向Function原型,true
console.log(Function.prototype.__proto__ === Object.prototype.__proto__); //前者为object原型,后者为null,false
console.log (Function.prototype.__proto___ === Object.prototype);//true
一、传统形式——原型链
function Grand(){};
Father.prototype = new Grand();//将Grand实例赋给Father的原型
function Father(){
this.name = "xuxu";
};
var father = new Father();
优点:
1.父类新增原型方法/原型属性,子类都能访问到
2.简单,易于实现
缺点:
1.过多的继承了没用的一些属性
2.来自原型对象的所有属性被所有实例共享
二、借用构造函数
function Person(name){
this.name = name;
}
function Student(name,age){
Person.call(this,name);//继承了Person
this.age = age;
}
var sttudent = new Student('jimo',18);
优点:
1.可以实现多继承,即call多个父级
缺点
1.不能继承借用构造函数的原型
2.每次构造函数都要多走一个函数
三、共享原型
Father.prototype.lastName = 'jimo';
function Father(){};
function Son(){};
Son.prototype = Father.prototype;//原型对象指向一个房间
var son = new Son();
优点:每次构造函数不会多走函数
缺点:指向一个索引(房间),不能随便更改自己的原型
四、圣杯模式(面试时问继承的标答)
var inherit = (function (){
var F = function(){};//定义一个中间构造函数,私有化变量
return function (target,origin){//target接受继承者,origin继承的目标
F.prototype = origin.prototype;//将继承的目标原型对象赋给F.prototype
target.prototype = new F();
//new一个实例对象赋给接受继承的target
//new后,Target.prototype指向的一个全新的地方
//改变Target的原型链就不会影响到Origin
target.prototype.constuctor = target;//将constructor指向自己
target.prototype.uber = origin.prototype;//保存自己真正继承的目标,以便后期访问
}
}());
解析:通过中间的构造函数(F)构建一个实例对象(new F()),让接受继承的构造函数(target)的原型属性指向这个实例对象(new F())(临时构造函数的实例对象),这样我们改变构造函数(target)原型属性的时候,影响的只是实例对象(new F())
五、其他
继承的方式还有很多(寄生式继承、组合继承、寄生组合式继承…),这些继承方式本人也只是知晓名字,本文仅写出我学习理解的并且个人觉得比较常用的继承方式,如果有兴趣可以再参看参考其他大佬的有关继承的博文。
博主开始运营自己的公众号啦,感兴趣的可以关注“飞羽逐星”微信公众号哦,拿起手机就能阅读感兴趣的博客啦!