前言
以下内容是对MDN JS对象属性 和 Object.defineProperty() 的笔记
JS对象属性
如何生成一个对象
-
Object.create(null)
产生一个真正的什么都没有的空对象 -
ES5 的
new Object()
等价于 ES6的Object.create(Object.prototype)
-
var d = {}
字面量指{}
看起来像(一个对象),那么它就是字面量
对象
以下代码中 a: 3
会覆盖 a: 1
var obj = {
a: 1,
b: 2,
a: 3
}
var a = 1
var b = 2
var object = {
a: a,
b: b
}
// 可以改写成
var object = {a, b}
动态属性名
var name = 'a'
var object = { [name]: 1 } // { a: 1 }
对属性的读写进行自定义的操作
var o = {
_age: 18,
get age(){return o._age}, // 读的时候
set age(value){ if(value<100){o._age = value}else{o._age = 100}} // 写的时候,自定义最大
}
var i = 0
Object.defineProperty(window, 'a', {
get(){
i += 1
return i
}
})
a === 1 && a === 2 && a ===3 // true
实现一个浅拷贝
var obj1 = {a:1, b:2, c:3}
var obj2 = {}
for(let key in obj1){
obj2[key] = obj1[key]
}
// 以上 for 简写成
var obj2 = Object.assign({}, obj1)
// 还可以简写成
var obj3 ={...obj1}
var aa = 1
var aa = 2
var obj4 = {...obj1, ...obj2, ...obj3, aa, bb, get x(){return 'hi'}}
变更原型
a.__proto__
是浏览器给自己用的,不要在任何时候使用a.__proto__
(它不受标准待见), ES6规定需要用Object.getPrototype(a)
来拿它的原型
var a = {}
var b = {
sayHi(){
console.log('hi')
}
}
a = Object.ceate(b) // 让对象和对象之间产生关联
a.__proto__ === b // true, 现在 b 是对象 a 的原型
b.__proto__ === Object.prototype // true
对象字面量表示法与JSON 可以理解为 JS的对象与JSON的对象的区别
Object.defineProperty()
var newObject = {
get x(){},
set x(value){}
}
newObject.x // 在读的时候走 get, 在写的时候走 set
假设有一个旧对象且属性已经写好的
var oldObject = {a: 1, b: 2}
我想给它加一个get set 怎么加?
加不了,定义的时间已经过了,无法重新定义
故只能用 Object.defineProperty()
来加
Object.defineProperty(oldObject, 'x', {
get(){
//这个里面 {} 是啥也没做的读的时候是 undefined
get x(){},
set x(value){}
}
})
undefined
它是不是关键字?
如果一个东西是关键字那么它是无法声明的
通过以上测试,可以得出 undefined
不是关键字
undefined
是一个变量
当 var undefined = 1
的时候,那么 undefined
打印出来的是几 ?
打印出来的是 undefined
不是说 undefined
是一个变量吗???
结论: undefined
是只读的变量 \
只读变量???
// 常量
const a = 1
a = 2 //直接报错
故 undefined
不是常量
那它就是变量
给 undefined
赋值,值却不变
故推倒出 它是一个 不可改变值的变量 \
如何让一个变量不可改变值?
undefined
其实就是 window.undefined
由以上判断出 undefined
其实就是 window
的一个只读属性
如何创建一个只读属性? \
var o = {
get name(){return 'hone'}
}
也可写成以下示例
如何把不可写的变成可写的
如何让writable
不可改呢?
写成
Object.defineProperty(o, 'engin', {writable: false, configurable: false})
可枚举
有些属性是可以遍历的(可以被遍历的就是可枚举),有些属性是遍历不到的
enumerable
enumerable: false
为不可枚举对象
作用:为true时,就是 可遍历的
使用以下方法就可以设置不可遍历的key,这样就可以在数组上添加一些属性同时不影响以前的代码
Object.definePropertys
var obj = {};
Object.defineProperties(obj, {
a: {
value: true,
writable: true
},
b: {
value: 'Hello',
writable: false
}
// a是可写的,b是不可写的
})
Vue文档 \
当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data
选项,Vue 将遍历此对象所有的 property,并使用 Object.defineProperty
把这些 property 全部转为 getter/setter。Object.defineProperty
是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。
对象可以用 Symbol 当 key
对象的 key 一般都是字符串, 在使用迭代的时候可能会使用 Symbol 作为 key
var s = Symbol()
var o = {
[s]: 1
}
获取对象是否有 Symbol 的 key 需要用以下方法
不可使用__propo__
已废弃: 该特性已经从 Web 标准中删除,虽然一些浏览器目前仍然支持它,但也许会在未来的某个时间停止支持,请尽量不要使用该特性。
为了更好的支持,建议只使用 Object.getPrototypeOf()
Object.defineProperty实际使用
let obj = {
姓: "高",
名: "圆圆",
get 姓名() {
return this.姓 + this.名;
},
set 姓名(xxx){
this.姓 = xxx[0]
this.名 = xxx.slice(1)
},
// 除非直接写age: 18
};
obj.姓名 = '高媛媛'
以上代码当我需要在 obj 上添加 obj.get Age 的时候,没有办法去添加,除非直接写
这个时候Object.defineProperty就有用了
Object.defineProperty
的第一个参数你要定义的对象,第二参数你要定义啥
var _xxx = 0
Object.defineProperty(obj, 'xxx', { // 我们给 obj 添加了一个虚拟属性 xxx, 它有 get 和 set
get(){ // get 后面不需要给名字了,这里就是 get xxx
return 0 // 每次获取的时候返回 0
}
set(x){ // 每次设置的时候你要给我一个新的 x
// 然后把这个 x 赋给 ??? xxx不存在的,于是我们需要去一个东西去放 xxx 这个值
}
})
var _xxx = 0
Object.defineProperty(obj, 'xxx', {
get(){
return _xxx // 如果要获取这个 xxx 就 return _xxx // 改成 return this.xxx 会死循环
}
set(value){
_xxx = value
}
})
以上代码就是在定义完一个对象之后,你想在它身上在额外的添加新的 get set 的时候,就可以通过Object.defineProperty来做
注意⚠️:一般来说我们定义的 get set 属性,是不存在的,不要去使用我们定义的那个 xxx ,它是不存在的,于是就需要用一个全局/局部 变量来放这个值