共计 2867 个字符,预计需要花费 8 分钟才能阅读完成。
这篇文章是看 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 |
对于原型对象的三个办法:isPrototype
,getPrototypeof
,setPrototypeOf
, 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 相似,只是仅针对 symbol | |
Reflect.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] ] |