对象的原型

隐式原型(对象的原型)

早期的ecma是没有规范如何查看原型
大部分浏览器给对象提供了一个属性 __proto__,可以让我们看一下这个原型对象

var obj = {name:"hahha"}
//只可以查看一下原型对象
console.log(obj.__proto__);
// es5之后提供了一个方法api,可以获取到对象原型
console.log(Object.getPrototypeOf(obj));
// 一般开发时用__proto__来做测试就行啦,api太长啦 不方便使用

每个对象中都是有[[prototype]],一般可以通过__proto__ 或者getPrototypeOf方法拿到
我们称之为隐式原型,我们一般不会对其做处理,也看不到,也不会直接用它

原型的作用
// 当我们从一个对象中获取某一个属性时,会触发其中的[[get]]操作
// 在查找的过程中过出发两个操作
// 1.在当前的对象中去查找对象的属性,如果找到就会直接使用
// 2.如果没有找到,就会沿着原型链去查找
// 原型和当前对象都没有age属性
console.log(obj.age);//undefined
// 可以向当前对象的原型中添加age属性
obj.__proto__.age = 18
console.log(obj.age);//18

显示原型(函数的原型)

二:显示原型(函数的对象)
`function foo(){

}`
函数他也是一个对象,所以他也有一个隐式原型__proto__ [[prototype]]
但函数还会多出来一个属性,叫做显示原型:prototype
prototype这个不是浏览器提供的,所以不存在浏览器兼容的问题,这个时ecma提供的
console.log(foo.prototype);

显示原型最重要的作用就是 第二条
当通过new关键字调用构造函数时
1.在内存中创建一个新的对象(空对象)
2.这个对象内部的[[prototype]]属性会被赋值为该构造函数的prototype属性
3.构造函数内部的this会指向创建吹来的新的对象
4.执行函数的内部代码(函数体代码)
5.如果构造函数没有返回非空对象,则返回创建出来的新对象

// 例如
function Person(){

}
var p1 = new Person()
var p2 = new Person()
// 由于指向内存空间的地址是一样的所以打印出来的结果为true
console.log(p1.__proto__==Person.prototype);//true
console.log(p2.__proto__==Person.prototype);//true
 
console.log(Person.prototype);//{}
// 打印函数原型显示为空对象,但其实并不是空的,而是因为里面的enmerable的值为false,不可枚举的
// 原型中其实包含一个属性叫做constructor
console.log(Person.prototype.constructor);
// constructor指向构造函数本身
// 我们也可以手动给原型添加属性
Person.prototype.sname='jeonghan'
var s1 = new Person()
// 当前对象s1上面并没有sname属性,是通过原型找到的sname
console.log(s1.sname);
// 我们可以通过这种方式给函数原型添加属性Person.prototype.sname='jeonghan'
// 但是当需要添加的属性变多的时候,就不方便了
// 我们可以采用直接修改整个prototype对象
Person.prototype = {
    // 这样就直接修改了整个原型对象
    name:"why",
    age:19,
    height:1.88
}
// 原型中还会有constructor属性,由于constructor属性是不可枚举的,这里通过defineproperty的方式添加
Object.defineProperty(Person.prototype,"constructor",{
    enumerable:false,
    configurable:true,
    writable:true,
    value:Person
})
var s2 = new Person()

its
1 声望0 粉丝