JavaScript继承(圣杯模式)的个人笔记

上期题目解答

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())

五、其他

继承的方式还有很多(寄生式继承、组合继承、寄生组合式继承…),这些继承方式本人也只是知晓名字,本文仅写出我学习理解的并且个人觉得比较常用的继承方式,如果有兴趣可以再参看参考其他大佬的有关继承的博文。

博主开始运营自己的公众号啦,感兴趣的可以关注“飞羽逐星”微信公众号哦,拿起手机就能阅读感兴趣的博客啦!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞羽逐星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值