JavaScript 对象解析

143 阅读6分钟

对象

定义:

  • 无序的数据集合
  • 建制对的集合

创建:

声明形式

let obj = { 'name': 'frank', 'age': 18 }

构造形式

let obj = new Object()

person=new Object();
person.firstname="John";
person.lastname="Doe";
person.age=50; 
person.eyecolor="blue";

image.png

函数形式

function Person(name,age){
  this.name = name;
  this.age = age;
  this.sayHi = function () {
    console.log("hello");
  };
}
var p = new Person("jimmy",18);

image.png

对象的属性

  • 属性名:每个key都是对象的属性名(property)
  • 属性值:每个 value 都是对象的属性值

奇怪的属性名:

所有属性名都会自动变成字符串

let obj = {
  1: 'a',
  3.2: 'b',
  1e2: true,
  1e-2: true,
  .234: true,
  0xFF: true
};
/** 以上每个属性的key值:
1其实是'1'
3.2其实是是'3.2'
1e2其实是'100'
1e-2其实是'0.01'
.234其实是'0.234'
0xFF其实是'255'

注意:
  • 键名是字符串,不是标识符,可以包含任意字符
  • 引号可省略,省略之后就只能写标识符
  • 渲算引号省略了,键名也还是字符串(重要) 访问一个对象的属性值可以通过 . 操作符[] 操作符 进行访问,举个粟子:

访问

. 操作符:要求属性名满足标识符的命名规范

[] 操作符:可以接受任意 UTF-8/Unicode 字符串作为属性名

let obj = {
  'first_name': 'Jon',
  age: 18,
  say: () => {
    console.log('hello')
  }
}

obj.age // 通过 .运算符 访问,18
obj['age'] // 通过 []操作符  访问,18
obj['first_name'] // 通过 []操作符 访问,Jon

变量做属性名:

如何使用变量做属性名?之前都是常量做属性名

let p1 = 'name'
let obj = { p1 : 'frank'} //这样写,属性名为 'p1'
let obj = { [p1] : 'frank' } //这样写,属性名为 'name'

  • 不加 [ ] 的属性名会自动变成字符串。
  • 加了 [ ] 则会当做变量求值。
  • 值如果不是字符串,则会自动变成字符串

除了字符串,symbol也能做属性名

let a = Symbol()
let obj = {[a]: 'Hello'}

对象操作

增加属性

1、修改或增加属性

(1)直接赋值

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']

(2)批量赋值

Object.assign(obj, {age: 18, gender: 'man'})

2、修改或增加公有属性

无法通过自身修改或增加共有属性

  • let obj = {}, obj2 = {} 共有 toString
  • obj.toString = 'xxx' 只会在改 obj 自身属性
  • obj2.toString 还是在原型上

我偏要修改或增加原型上的属性

  • obj.__proto__.toString = 'xxx' // 不推荐用 __proto__
  • Object.prototype.toString = 'xxx'
  • 一般来说,不要修改原型,会引起很多问题

3、修改隐藏属性

不推荐使用__proto__

let obj = {name:'frank'}
let obj2 = {name: 'jack'}
let common = {kind: 'human'}
obj.__proto__ = common
obj2.__proto__ = common


推荐使用 Object.create

let obj = Object.create(common)
obj.name = 'frank'
let obj2 = Object.create(common)
obj2.name = 'jack'

规范大概的意思是,要改就一开始就改,别后来再改

删除属性

delete命令用于删除对象的属性,删除成功后返回true

举例:

(1)

注:只能用'xxx' in obj 查看属性名是否还在对象中:true表示在,false表示不在

(2)

①语句'xxx' in obj && obj.xxx === undefined返回true,表示属性xxx还在obj中,而且属性xxx的值是undefined

②注意obj.xxx === undefined不能断定'xxx' 是否为obj的属性。

查看属性

查看一个对象本身的所有属性,可以使用Object.keys方法。

  • 查看一个对象的所有自身属性: Object.keys(obj)
var obj = {
  key1: 1,
  key2: 2
};

Object.keys(obj);
// ['key1', 'key2']
  • 查看一个对象的所有自身属性值: Object.values(obj)
  • 查看一个对象的所有自身的属性和值:直接对象名就行obj或者Object.entries(obj)
  • 查看自身+共有属性: console.dir(obj)
  • 查看共有属性: 自己依次用Object.keys打印出obj.__ proto_
  • 判断一个属性是自身的还是共有的: obj.hasOwnProperty('属性名')( 返回true说明该属性是自身属性,返回false说明该属性是共有属性)
  • 'key' in obj查看属性名是否还在对象中:true表示在,false表示不在

查看一个对象的一个属性

  • 中括号语法: obj['key']obj['k'+'ey']
  • 点语法: obj.key
  • 坑新人语法:obj[key] // 变量 key 值一般不为 'key'

举例

let list = ['name','age','gender']
let person = {
    name: 'yy', age : 18, gender : 'woman'
}
for (let i = 0; i < list.length; i++) {
    let name = list [i]
    console.log(person.name)  //重点
}
// 结果为person的第一个属性值yy*3

let list = ['name','age','gender']
let person = {
    name: 'yy', age : 18, gender : 'woman'
}
for (let i = 0; i < list.length; i++) {
    let name = list [i]
    console.log(person[name]) //重点
}
// 结果为person的所有属性值yy、18、woman

属性的遍历

for...in循环用来遍历一个对象的全部属性。

var obj = {a: 1, b: 2, c: 3};

for (var i in obj) {
  console.log('键名:', i);
  console.log('键值:', obj[i]);
}
// 键名: a
// 键值: 1
// 键名: b
// 键值: 2
// 键名: c
// 键值: 3

ES6

对象的扩展

属性的简洁表示法

ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。

const foo = 'bar';
const baz = {foo};
baz // {foo: "bar"}

// 等同于
const baz = {foo: foo};

上面代码中,变量foo直接写在大括号里面。这时,属性名就是变量名, 属性值就是变量值。下面是另一个例子。

function f(x, y) {
  return {x, y};
}

// 等同于

function f(x, y) {
  return {x: x, y: y};
}

f(1, 2) // Object {x: 1, y: 2}

除了属性简写,方法也可以简写。

const o = {
  method() {
    return "Hello!";
  }
};

// 等同于

const o = {
  method: function() {
    return "Hello!";
  }
};

例子

let birth = '2000/01/01';

const Person = {
  name: '张三',
  //等同于birth: birth
  birth,
  // 等同于hello: function ()...
  hello() { console.log('我的名字是', this.name); }
};

这种写法用于函数的返回值,将会非常方便。

function getPoint() {
  const x = 1;
  const y = 10;
  return {x, y};
}

getPoint()
// {x:1, y:10}

CommonJS 模块输出一组变量,就非常合适使用简洁写法。

let ms = {};
function getItem (key) {
  return key in ms ? ms[key] : null;
}
function setItem (key, value) {
  ms[key] = value;
}
function clear () {
  ms = {};
}

module.exports = { getItem, setItem, clear };
// 等同于
module.exports = {
  getItem: getItem,
  setItem: setItem,
  clear: clear
};

扩展运算符 

对象的扩展运算符(...)用于取出参数对象的所有可遍历属性,拷贝到当前对象之中。

let z = { a: 3, b: 4 };
let n = { ...z };
n // { a: 3, b: 4 }

ES6方法

Object.is()

Object.is用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。

Object.is('foo', 'foo')
// true
Object.is({}, {})
// false

Object.assign()浅拷贝

Object.assign()方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。

const target = { a: 1 };

const source1 = { b: 2 };
const source2 = { c: 3 };

Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}

Object.assign()方法的第一个参数是目标对象,后面的参数都是源对象。

注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。

const target = { a: 1, b: 1 };

const source1 = { b: 2, c: 2 };
const source2 = { c: 3 };

Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}