javascript原型,原型链知识点梳理

javascript原型
要理解原型我们要先问自己几个问题,1.什么是原型对象?2.为什么要用原型?带着这些问题有助于我们更好的去理解原型。
1.什么是原型对象呢?我们创建的每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,即原型对象,这个对象可以共享属性和方法,所有同一个类的实例对象都可以访问原型对象。
用简单的白话可以这样理解:每个函数里都有prototype(包括构造函数),构造函数创建的实例对象里有__proto__原型
注意:当普通函数调用prototype是没有作用的。只有构造函数形式调用prototype时,它所创建的实例对象都有一个隐含的属性__proto__,实例的__proto__指向原型对象,看以下简单例子方便理解:

function Myclass(){
}
var mc=new Myclass()
var mc1=new Myclass()
console.log(Myclass.prototype == mc.__proto__ )
console.log(Myclass.prototype == mc1.__proto__ )
//返回结果都为true 

此处先打断一下思路,大概了解含义就行,那我们为什么要去用这个原型对象呢?
(1)我们平时创建对象可以用Objcet构造函数或者对象字面量来创建,但是这样创建缺点很明显:使用同一个接口创建多个对象时,会产生大量的重复代码,如何解决呢?引入工厂模式
(2)通过工厂模式,我们就可以解决大量代码重复的问题,但工厂模式也有缺点,如下面的代码,因为都是通过Object创建的实例,结果都是Object,所以根本无法解决对象的识别问题,如何解决呢?引入构造函数
这个例子创建人和狗都是以Object为标识,无法区分

function createPerson(name,age,job){
	var o = new Objecct();
	o.name=name;
	o.age=age;
	o.job=job;
	return o;
}
var person1=createPerson('swk',22,'kfc');
var person2=createPerson('csf',23,'mc');

function createDog(name,age,job){
	var o = new Objecct();
	o.name=name;
	o.age=age;
	o.job=job;
	return o;
}
var dog1=createDog('swk',22,'kfc');
var dog2=createDog('csf',23,'mc');

(3)构造函数可以有效解决工厂模式的缺点,但是以下的构造函数还是不够完美,还是有缺点,以下例子person1和person2都会有say方法,构造函数每执行一次都会创建一个新的空间存储say函数,这样存储地址不同,person1.say == person2.say 结果为false,证明他们存储在不同的空间,但是作用却是一样的,这样就导致来内存空间大量浪费。所以我们可以完善一下构造函数

function Person(name,age){
	this.name=name;
	this.age=age;
	this.say=function(){
		console.log('haha')	
	}
}
var person1=new Person('yx',11);
var person2=new Person('uu',22);

function Dog(name,age){}
var dog=new Dog()
//用构造函数即可区分开不同的类型,用Person创建的就是person类下对象,用Dog创建的就说Dog类下对象
//我们也可以用instanceof操作符来检测结果
console.log(dog instanceof Person) //false
console.log(dog instanceof Dog)//true
console.log(dog instanceof Object)//true(所有对象都是Objcet后代)

(4)我们可以把构造函数内部的函数拿出来,放到全局里面,这样就只会占用一个空间,不会占用空间,对性能有来很大提升。但是问题又来了,这样会污染了全局作用域的命名空间,很不安全。如何解决呢?引入了原型对象

function Person(name,age){
	this.name=name;
	this.age=age;
	}
function say(){
	console.log('xixi')
}
var person1=new Person('yx',11);
var person2=new Person('xx',12);

(5)原型模式可以有效解决内存浪费和全局污染的问题,如下面例子,person1和penson2使用的say方法相同,在同一空间;也没有在全局里面定义方法,不会污染全局;

function Person(name,age){
	this.name=name;
	this.age=age;
	}
	Person.prototype.say=function(){
		alter('xixi')
}
var person1=new Person();
var person2=new Person();
console.log(person1.say == person2.say)//true

到这里我们也应该清楚了为什么要去用原型的好处,它是由于一个个不同的问题,最终选择了原型这种比较好的方式来处理问题。

原型引出来以后,我们也可以简单的去理解原型链是什么了

function Person(){}
var person1=new Person();
person1.name='yuyu'
console.log(person1.name);
console.log(person1.hasOwnPropery("name"));//true
//结果为yuyu,实例对象第一步会在自身上找属性,我们可以用hasOwnPropery来协助验证对象中是否含有这个属性

function Person(){}
var person1=new Person();
Person.prototype.name='yuyu1';
console.log(person1.name);
console.log(person1.hasOwnPropery("name"))//false
console.log(person1.__proto__.hasOwnPropery("name"))//true
//结果上yuyu1,自身上没有name属性,就会根据隐含的__proto__指向到原型对象去找name

function Person(){}
var person1=new Person();
Object.prototype.name='yuyu2'
console.log(person1.name)//yuyu2
console.log(person1.hasOwnPropery("name"))//false
console.log(person1.__proto__.hasOwnPropery("name"))//false
console.log(person1.__proto__.__proto__.hasOwnPropery("name"))//true

//结果是yuyu2,自身没有,去原型对象里找还是没有,(因为原型对象也是对象,对象就会有一个__proto__),就会根据__proto__继续找到Object,如歌Object还没有就会返回null

以上这个查找属性的过程就是一个原型链,到此原型和原型链也应该有个清楚的认识了。

同时在此补上一个简单的面试题:
创建对象的方法?
1、对象字面量 var obj={};
2、构造函数 var obj=new Object();
3、工厂模式创建
4、自定义构造函数创建
5、构造函数和原型模式创建
6、Object.create()创建

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值