一、关于对象
1、什么是对象?
- 简单说,对象就是一组“键值对”(key-value)的集合,是一种无序的复合数据集合。
2、键名有哪些需要注意的细节?
- 键名是字符串,不是标识符。
- 引号可省略,省略之后就键名只能写标识符。
- 就算引号省略了,键名也还是字符串。
- 所有属性名都会自动变成字符串
let obj = {1: 'a', 3.2: 'b', 1e2: true, 1e-2: true,.234: true,0xFF: true};
Object.keys(obj) => ["1", "100", "255", "3.2", "0.01", "0.234"]
3、对象的三种写法
let obj = { 'name': 'frank', 'age': 18 } //简单写法,对象名字为 obj。
let obj = new Object({'name': 'frank'}) //正规写法,对象名字为 obj。
console.log({ 'name': 'frank', 'age': 18 }) //打印对象,对象没有名字
4、字符串和标识符的区别
- 标识符:代码中用来标识变量、函数、或属性的字符序列。
- 在 JavaScript 中,标识符只能包含字母或数字或下划线(“_”)或美元符号(“$”),且不能以数字开头。
- 标识符与字符串不同之处在于字符串是数据,而标识符是代码的一部分。
5、对象的隐藏属性
- JS 中每一个对象都有一个隐藏属性
- 这个隐藏属性储存着其共有属性组成的对象的地址
- 这个共有属性组成的对象叫做原型,也就是说,隐藏属性储存着原型的地址。
- 注意,原型不等于共有属性,原型是共有属性的集合。
var obj = {}
obj.toString() // 居然不报错 ,因为 obj 的隐藏属性对应的对象上有 toString()。
二、增删改查
1、删除
- 语法
delete obj.xxx 或 delete obj['xxx']
- 查询是否删除成功的方法
‘xxx' in obj => true / false
obj.name = undefined
'xxx' in obj && obj.xxx === undefined
# 第一种方法
let obj={name:'wuguangbin','中文':'吴廣彬'}
obj => {name: 'wuguangbin', 中文: '吴廣彬'}
delete obj.name => true
'name' in obj => false
obj => {中文: '吴廣彬'} // 属性名和属性值都删除
# 第二种方法
let obj={name:'wuguangbin','中文':'吴廣彬'}
obj => {name: 'wuguangbin', 中文: '吴廣彬'}
obj.name = undefined
'name' in obj => false
obj => {name: undefined, 中文: '吴廣彬'} // 只删除属性值,undefined 的意思为'空'。
'name' in obj && obj.xxx === undefined => true // 判断属性名为name,但属性值为undefinde的方法。
- 不能使用 obj.xxx === undefined 来判断 obj 是否拥有 xxx 属性
# 错误的判断方法
let obj = {}
let obj2 = {x:undefined}
obj.x === undefined => true // obj 没有属性 X
obj2.x === undefined => true // obj 拥有属性 x,它的值为 undefined。
# 正确的判断方法
'x' in obj => false
'x' in obj2 => true
2、查看
- 语法
obj['key']
obj.key
obj[key] ('key'是字符串,key是变量)
- 查看所有属性的方法
# 五种方法
obj // 查看所有键值对
obj.__proto__ // 查看共有属性
Object.keys(obj) // 查看所有属性名
console.dir(obj) // 查看所有自身属性和共有属性
obj.hasOwnProperty('toString') // 判断一个属性是自身的还是共有的
# 示例展示
let obj = { 'name': 'frank', 'aaa': 18 ,ccc:'NaN'}
obj => {name: 'frank', aaa: 18, ccc: 'NaN'}
aaa: 18
ccc: "NaN"
name: "frank"
[[Prototype]]: Object //可展开
obj.__proto__ =>
{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
Object.keys(obj) => ['name', 'aaa', 'ccc']
console.dir(obj) =>
name: "frank"
aaa: 18
ccc: "NaN"
[[Prototype]]: Object
obj.hasOwnProperty('toString') => false
3、修改或增加
- 直接赋值
# let obj = {name: 'frank'} // name 是字符串
obj.name = 'frank' // name 是字符串
obj['name'] = 'frank'
obj[name] = 'frank' // 错,name 是变量。
obj['na'+'me'] = 'frank'
# let key = 'name'; obj[key] = 'frank'
# let key = 'name'; obj.key = 'frank' // 错 因为 obj.key 等价于 obj['key'],但 key 是一个变量,而 'key'是字符串。
- 批量赋值
let obj = { 'name': 'frank', 'aaa': 18 ,ccc:'NaN'}
Object.assign(obj,{a:1,b:2,c:3}) =>
{name: 'frank', aaa: 18, ccc: 'NaN', a: 1, b: 2, …}
- 修改或增加共用属性
# 无法通过自身修改或增加共有属性
let obj = {}, obj2 = {} // 共有 toString
obj.toString = 'xxx' // 只会在改 obj 自身属性
obj2.toString // 还是在原型上
# 非要修改或增加共有属性
obj.__proto__.toString = 'xxx' // 不推荐用 __proto__ Object.prototype.toString = 'xxx'
# 一般来说,不修改原型,会引起很多问题。
- 创建原型链
let person ={name:'jake'}
let common = {a:1,b:2,c:3}
person.__proto__ = common // person.__proto__ 中加上 common 的地址
person => {name: 'jake'}
[[Prototype]]: Object
a: 1
b: 2
c: 3 // 新增 Prototype
[[Prototype]]: Object
三、区分 'xxx' in obj 和 obj.hasOwnProperty('xxx')
- 'xxx' in obj 用于查看对象里面是否有属性名 'xxx'
- obj.hasOwnProperty('xxx') 只检查自身属性里面是否有属性名 'xxx',配合操作符 in 检查是否为共有属性。
代码示例1:
let obj = {name:'frank'}
'name' in Object => true
obj.hasOwnProperty('name') => true
let common = {name:'jack'}
obj.__proto__ = common
delete obj.name
'name' in Object => true
obj.hasOwnProperty('name') => false // 自身属性中的 name 已被删除,所以返回 false。
代码示例2:
let obj = {'age': 18 }
let obj = Object.create({'name':'wudada'})
'name' in obj => true // 对象 obj 中存在'name'属性名,但不确定在自身属性还是在共有属性里面。
obj.hasOwnProperty('name') => false // 确定:不在自身属性,在共有属性
四、区分 let obj = Object.create() 和 let obj = new Object()
- 一个在自身属性上创建,另一个在原型上创建。
let obj = Object.create({name:'wudada'})
obj =>
{}
[[Prototype]]: Object
name: "wudada" // 在原型上
[[Prototype]]: Object
let obj = new Object({name:'wudada'})
obj =>
{name: 'wudada'}
name: "wudada" // 在自身属性上
[[Prototype]]: Object