这篇文章是看js红宝书第8章,记的对于对象的笔记(第二篇)。

创建对象的几种模式:

工厂模式:

工厂是函数的意思。工厂模式外围是定义一个返回全新对象的函数。

  function getObj(name, age) {    let obj = {}    obj.name = name    obj.age = age    return obj  }  let person1 = getObj("cc", 31)

毛病:不晓得新创建的对象是什么类型

构造函数模式:

通过一个构造函数,失去一个对象实例。
构造函数和工厂模式区别是:
1,构造函数函数体加了this
2,构造函数没有return
3,结构函数调用时,用new关键字

  function CreateObj(name, age) {    this.name = name    this.age = age  }  let person1 = new CreateObj("cc", 31)  console.log(person1)  console.log(person1.constructor === CreateObj); // true  console.log(person1 instanceof CreateObj); // true

对于构造函数的两个问题:
1,构造函数和一般函数惟一区别是调用形式。构造函数要用new关键字。如果不必new,则是往Global对象上加属性。上面例子中,CreateObj办法,往window对象上加了name和age属性

  function CreateObj(name, age) {    this.name = name    this.age = age  }  CreateObj('cc', 10)  console.log(window.name) // 'cc'

2,构造函数存在的问题: 构造函数体内的办法,每次创立一个实例,都会创立一遍。

person1.sayName( ) === person2.sayName( ) // false

解决办法是,将sayName定义在createObj里面。

  function sayName() {    console.log(this.name)  }  function CreatePerson(name, age) {    this.name = name    this.age = age    this.sayName = sayName  }  let person1 = new CreatePerson('joy', 31)  person1.sayName()

然而,这样会让自定义类型援用的代码不能很好聚在一起。

原型模式:

原理是,每个函数都有一个prototype属性。prototype是一个对象,外面定义的属性和办法会被所有实例共享。
对于原型模式,有两个等式:

  function Person() {  }  let person1 = new Person()  console.log(person1.__proto__ === Person.prototype)   // true  console.log(Person.prototype.constructor === Person); // true

对于原型对象的三个办法:isPrototypegetPrototypeofsetPrototypeOf, Object.create()

// isPrototypeOf判断构造函数的原型对象是否是实例的原型对象function Person() {}  let person1 = new Person()  console.log(Person.prototype.isPrototypeOf(person1)); // true
// 获取对象的原型对象  function Person() {}  let person1 = new Person()  console.log(Object.getPrototypeOf(person1) === Person.prototype);
// 将某个对象,设为另一个对象的原型对象  let person1 = {name: "cc"}  let person2 = {age: 32}  Object.setPrototypeOf(person1,person2)  console.log(person1.name, person1.age); // cc  32
// 以某个对象为原型对象,创立一个新对象    let person1 = {name: "cc"}  let person2 = Object.create(person1)  person2.age = 30  console.log(person2.name, person2.age);

当拜访一个对象person的name属性时,是依照以下步骤去拜访:
1,person上如果有name属性(即使这个属性是null,也会返回null),返回name属性值;没有,持续去原型对象Person.prototype上找
2,如果原型上有name属性,返回原型上name属性值;没有,则返回undefined

判断一个属性是在实例上,还是在原型上,能够用hasOwnProperty

  function Person() {}  Person.prototype.name = "cc"  let person1 = new Person()  console.log(person1.name) // 'cc'  console.log(person1.hasOwnProperty("name")); // false

判断一个对象上是否有个某个属性,用in操作符

// 对象本身 or 原型上找到,都返回true  function Person() {}  Person.prototype.name = "cc"  let person1 = new Person()  console.log("name" in person1)  // true  console.log(person1.hasOwnProperty("name")); // false

拜访对象的属性的办法:

Object.keys( )for ... in // 继承属性也会遍历进去Object.getOwnPropertyNames(obj) // 会列出可枚举和不可枚举属性,其余和 Object.keys( )后果一样Object.getOwnPropertySymbols(obj) // 和getOwnPropertyNames相似,只是仅针对symbolReflect.ownKeys(obj) // 和Object.keys( )后果一样

其余拜访对象属性和属性值的办法:
Object.values( ) 对象值组成的数组,会省掉Symbol型。
Object.entries( ) 对象键值对组成的数组,会将键,转化成字符串,省掉Symbol型。

 function Person() {}  Person.prototype.name = "cc"  let person = new Person()  person.age = 21  let sy = Symbol('sy')  person[sy] = 'smile'  console.log(Object.values(person)) // [ 21 ]  console.log(Object.entries(person)) // [ [ 'age', 21 ] ]