原型和原型链

51 阅读3分钟

原型对象

每个函数类型的数据,都有一个prototype属性,这个属性值是一个对象,称为原型对象,原型对象的作用是用来存放实例对象的公有属性和公有方法。

显示原型

每个函数类型的数据,都有一个prototype属性

隐式原型

每个对象都有一个__proto__属性,指向原型对象

image.png

原型链

查找某个对象的属性,自身和原型对象上都没有,就继续往原型对象的原型对象上找,整个查找过程都是顺着__proto__属性,一步一步往上查找,直至null,这样一层链式结构,就是原型链

Object对象常用方法

(1)Object.getPrototypeOf(obj): 返回参数对象的原型,获取原型对象,相当于__proto__

(2) Object.getOwnPrototypeNames(obj): 返回一个数组,其自有的可枚举和不可枚举的属性名称被返回

(3) Object.create(): 以一个现有对象作为原型,创建一个新对象, 新对象是空对象,没有原型,不继承任何对象

(4) Object.prototype.hasOwnProperty():对象自有属性(而不是继承来的属性)中是否具有指定的属性

Object.create

Object.create(proto, propertiesObject)

proto: 新创建对象的原型对象

propertiesObject: 该传入对象(可枚举的自有属性)将为新创建的对象添加具有对应属性名称的属性描述符

var obj44 = Object.create({}, { name: { value: '123' } })
console.log(obj44) // {}
let  obj =  Object.create({}, {
  name: {
    value: "名称",
    configurable: true, // 是否能通过delete删除属性
    enumerable: false, // 是否可遍历
    writable: true // 是否可修改
  },
  age: {
    value: "123",
    configurable: true,
    enumerable: true,
    writable: true
  }
})
// enumerable是false则不会在新对象上添加该属性
console.log(obj) // {age: '123'}
  • 通过Object.create实现原型继承
let person = {
  name: '人',
  age: 18,
  say() {
    console.log('你好')
  }
}

// 原型继承
var obj1 = Object.create(person, {
  name: {
    value: '名称'
  },
  like : {
    value: 'study'
  }
})

console.log(2, obj1) // {}
console.log(3, obj1.name) // 名称
console.log(4, obj1.age) // 18
obj1.say() // 你好
console.log(6, obj1.__proto__ === person) // true
  • 实例
var a = {a:1,b:2}  
var b = Object.create(a) // b继承a, b是空对象
var c = Object.create(b) // c继承b, c是空对象
说出他们之间的指向关系?

o = Object.create(null);
// 等价于:
o = { __proto__: null };
b.__proto指向a, c.__proto__指向b

console.log(b.__proto__ === a) // true, b.__proto__: {a:1,b:2} 
console.log(c.__proto__ === b) // true, c.__proto__: {}

for...in

(1) for..in会遍历对象中所有可枚举属性(包括自有属性和继承属性)

(2) 若是将一个属性变为不可枚举属性, for...in无法枚举

let obj8 = {
  itemA: 'itemA',
  itemB: 'itemB'
}
let newObj = Object.create(obj8)
newObj.newItemA = 'newItemA'
newObj.newItemB = 'newItemB'

for(let i in newObj) {
  console.log(99, i)
}
// 若是将一个属性变为不可枚举属性, for...in无法枚举
Object.defineProperty(newObj, 'newItemA', {
  enumerable: false
})
for(let i in newObj) {
  console.log(7, i)
}

创建对象的方式

  • 字面量
  • new Object
  • Object.create()
let obj4 = { name: 111}
let obj5 = new Object({name: 222})
let obj6 = Object.create({name: 333})
console.log(obj4) //  { name: 111}
console.log(obj5) // {name: 222}
console.log(obj6) // {}

console.log(obj4.__proto__ === Object.prototype) // true
console.log(obj5.__proto__ === Object.prototype) // true
console.log(obj6.__proto__) // { name: 333 }

(1)使用字面量的形式创建的对象,原型指向Object.prototype

(2) 使用new形式创建的对象,实例的proto指向Object的prototype

(3) 用Object.create创建的对象,原型指向传入的第一个参数

参考文献

juejin.cn/post/725560… blog.csdn.net/wswq2505655…