JS 对象的基本用法

314 阅读4分钟

一、关于对象

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 检查是否为共有属性。
代码示例1let 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。

代码示例2let 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