defineProperties可以定义多个属性描述符
var obj = {// 私有属性(js里面是没有严格意义的私有属性)_age: 18,_eat: function() {}
}Object.defineProperties(obj, {name: {configurable: true,enumerable: true,writable: true,value: "why"},age: {configurable: false,enumerable: false,get: function () {return this._age},set: function (value) {this._age = value}}
})
console.log(obj)
//
对象方法补充
1、获取对象的属性描述符
- getOwnPropertyDescriptor
- getOwnPropertyDescriptors
var obj = {// 私有属性(js里面是没有严格意义的私有属性)_age: 18,_eat: function() {}
}Object.defineProperties(obj, {name: {configurable: true,enumerable: true,writable: true,value: "why"},age: {configurable: false,enumerable: false,get: function () {return this._age},set: function (value) {this._age = value}}
})
// 获取某一个特定属性的属性描述符
console.log(Object.getOwnPropertyDescriptor(obj,'name'))
// 获取对象的所有属性描述符
console.log(Object.getOwnPropertyDescriptors(obj))
执行结果:
2、禁止对象扩展新属性:preventExtensions
3、禁止对象配置/删除里的属性
var obj = {name: 'why',age: 8
}// 禁止对象继续添加新的属性
Object.preventExtensions(obj)obj.height = 1.88
obj.address = "成都市"console.log(obj)Object.seal(obj)delete obj.nameconsole.log(obj)
分别不注释Object.seal(obj)和注释Object.seal(obj)的结果
4、让属性不可以修改
var obj = {name: 'why',age: 8
}// 让属性不可以修改(writable:false)
Object.freeze(obj)obj.name = 'kobe'
console.log(obj.name)
执行结果
创建多个对象的方案
工厂模式
- 工厂模式其实是一种常见的设计模式
- 通常我们会有一个工厂方法,通过该工厂方法我们可以产生想要的对象
// 工厂模式: 工厂函数
function createPerson(name, age, height, address) {var p = {}p.name = namep.age = agep.height = heightp.address = addressp.eating = function () {console.log(this.name + "在吃东西~")},p.running = function () {console.log(this.name + "在跑步!")}return p
}var p1 = createPerson('张三', 18, 1.78, '北京市')
var p2 = createPerson('李四', 23, 1.88, '成都市')
var p3 = createPerson('王麻子', 28, 1.98, '重庆市')// 工厂模式的缺点(获取不到对象最真实的类型)
console.log(p1, p2, p3)
构造函数
// 构造函数
function person(name, age, height, address) {this.name = namethis.age = agethis.height = heightthis.address = addressthis.eating = function () {console.log(this.name + "在吃东西~")},this.running = function () {console.log(this.name + "在跑步!")}
}var p1 = new person('张三', 18, 1.78, '北京市')
console.log(p1)
规范:构造函数的首字母一般是大写
原型的概念
// 我们每一个对象都有一个[[prototype]],这个属性可以称之为对象的原型(隐式原型)var obj = { name: 'why'} // [[prototype]]
var info = {} // [[prototype]]// 1、解释原型的概念和看一下原型
// 早期的ECMA是没有规范如何查看[[prototype]]// 给对象中提供了一个属性,可以让我们查看一下这个原型对象(浏览器提供)
// __proto__// console.log(obj.__proto__)
// console.log(info.__proto__)var obj = { name: 'why', __proto__: {}}// ES5之后提供的Object.getPrototypeOf// console.log(Object.getPrototypeOf(obj))// 2、原型有什么用
// 当我们从一个对象中获取某一个属性时,它会触发[[get]]操作
// 1、在当前对象中去查找对应的属性,如果找到就直接使用
// 2、如果没有找到,那么会沿着它的原型去查找[[prototype]]
// obj.age = 18
obj.__proto__.age = 18console.log(obj.age)
Person构造函数原型内存图
函数原型上的属性-constructor
赋值为新的对象
function foo() {}// foo.prototype这个对象中有一个constructor的属性
// console.log(foo.prototype)
// console.log(Object.getOwnPropertyDescriptor(foo.prototype))// Object.defineProperty(foo.prototype, 'constructor', {
// enumerable: true,
// configurable: true,
// writable: true,
// value: "哈哈哈哈"
// })// console.log(foo.prototype)// prototype.constructor = 构造函数本身// console.log(foo.prototype.constructor) // [Function: foo]
// console.log(foo.prototype.constructor.name)// console.log(foo.prototype.constructor.prototype.constructor.prototype.constructor)// 2. 我们也可以添加自己的属性
// foo.prototype.name = "why"
// foo.prototype.age = 18
// foo.prototype.height = 180
// foo.prototype.eating = function () {// }// var f1 = new foo()
// console.log(f1.name, f1.age)// 3.直接修改整个prototype
foo.prototype = {// constructor: foo,name: "why",age: 18,height: 180
}var f1 = new foo()
console.log(f1.name, f1.age, f1.height)// 真实开发中我们通过Object.defineProperty方式添加constructor
Object.defineProperty(foo.prototype, 'constructor', {enumerable: true,configurable: true,writable: true,value: foo
})
创建对象方案-原型和构造函数
function Person(name, age, height, address) {this.name = namethis.age = agethis.height = heightthis.address = address
}Person.prototype.eating = function() {console.log(this.name + "在吃东西~")
}Person.prototype.running = function() {console.log(this.name + "在跑步~")
}var p1 = new Person('why', 18, 1.88, '北京市')
var p2 = new Person('kobe', 20, 1.98, '洛杉矶市')p1.eating()
p2.running()