在接触原型与原型链中,我产生了以下几个疑问:
1.构造函数、对象等概念是什么?原型对象是什么?
2.不是说只有实例对象有__proto__属性,为什么prototype(原型对象)也有__proto__属性呢?
3.为什么构造函数要单独将一些方法属性提出来,写入prototype中?
在原型链中,我们有几个概念:构造函数、原型对象、实例对象。
function Person(){
}
Person.prototype.age=18;
Person.prototype.name=function(){
return 'lk'};
var person = new Person();
console.log(Person.prototype);
console.log(person.__proto__);
console.log(Person.prototype.constructor);
我们可以看到
//不写在原型对象里
function Person(){
name:'lk';
sayhi=function(){
return 'hi'};
}
如果要为Person这个构造函数创建成千上万个实例person1、person2…person10000,那就得不停的创建sayhi函数;那既然都是一样的功能,就写在一个地方,这些Person的实例们去一个地方(原型对象)拿就好啦!
所以我们将一些公共属性与方法写入原型对象里。
1.每个构造函数都有一个prototype属性,指向自己的原型对象
2.每个对象都有 __proto__属性 ,指向自己构造函数的原型对象(要用没写入构造函数里的方法,所以指向的是构造函数的原型对象)
这下看实例对象、构造函数、原型对象的关系,是不是清楚一些了?
我们说过,原型对象也是一个对象,具有__proto__属性。所以它也有自己的构造函数(本图是Object构造器/构造函数),原型对象的__proto__属性指向自己的构造函数的原型对象(Object.prototype);而Object.prototype的原型对象是null。
这样通过__proto__属性链接起来的一条路线,就叫做原型链。
用new和Object.create都可以创建对象,那么为什么要再有另一种方式呢?
①语法
Object.create(proto,[propertiesObject])
proto:新创建对象的原型对象
propertiesObject:可选。要添加到新对象的可枚举的属性。
②举个简单的栗子看看
<script>
//自己写的原型对象
const a = {
name:'lk',
sayhi:function(){
console.log('hi')}
}
//创建一个新对象,a是它的原型对象
const abab = Object.create(a,{
height:{
writable:true,
configurable:true,
value:180
}
})
//看看创建的这个对象
console.log(abab)
abab.sayhi()
</script>
更正:下图原型对象a的原型对象应该是Object.prototype,写错了
①代码看下
//2.细说区别
//2.1用字面量创建对象:原型对象是Object
const b = {
name:'lk',
sayhi:function(){
console.log('hi')}
}
console.log(b)
//2.2用Object.create创建对象,给定一个原型对象为null
var baby = Object.create(null,{
height:{
value:18
}
})
console.log(baby)
通过上面原型与原型链的学习,我们可以猜到baby这个对象的原型对象是空。
通过上面原型与原型链的学习,我们可以猜到baby这个对象的原型对象是空。 我们也可以推测这几个对象(还有1里面的abab对象):
1.abab对象的原型对象是a,a的原型对象是Object.prototype。abab对象可以使用Object.prototype里的属性与方法。在原型链上。
2.用字面量创建的b对象当然也可以使用Object.prototype里的属性与方法。
3.baby对象的原型对象是null,没有什么方法。
试试:
//2.3看看对象abab、b、baby的原型链上的方法toString
console.log(abab.toString());
console.log(b.toString());
console.log(baby.toString());//报错
当然,我们如果指定原型对象为Object.prototype,和用字面量/new创建的对象就是一模一样的了。
//3.指定原型对象为Object.prototype
var cdcd =Object.create(Object.prototype);
console.log(cdcd);
console.log(cdcd.toString())
②总结一下
其实他俩的区别大家已经心知肚明了:
Object.create可以指定任意的原型对象,常用于创建一个以空对象为原型对象的实例。