JavaScript之对象(二)

简介: JavaScript之对象(二)
看红宝书+查资料,重新梳理JavaScript的知识。

合并对象 Object.assign()

Object.assign()可以用来将原对象的属性合并到目标对象上,而且这个方法还会返回合并后的目标对象。它会使用源对象上的[[Get]]取得属性的值,然后使用目标对象上的[[Set]]设置属性的值。

let target = {
    name: 'clz'
};

let source = {
    age: 21
};

let result = null;

// 也会返回修改后的目标对象
result = Object.assign(target, source);

console.log('target: ', target);
console.log('source: ', source);
console.log('result: ', result);

console.log(target === result);

合并对象是浅克隆

合并对象是浅克隆。所以如果合并的属性是对象,那么修改源对象会修改到目标对象

let target = {
    name: 'clz'
};

let source = {
    job: {
        salary: 1
    }
};

Object.assign(target, source);

source.job.salary = 999

console.log('target: ', target)
console.log('source', source)

image-20220423200456546

多个源对象合并

上面的例子中,Object.assign只接收了两个参数,第一个参数是目标对象,第二个参数是源对象。但是呢,其实它并不只是能够接收两个参数,可以接收多个参数,第一个参数是目标对象,其他的都是源对象,都会合并到目标对象上

let target = {};
let source1 = {
    name: 'clz'
};
let source2 = {
    age: 19
};

Object.assign(target, source1, source2);
console.log(target);    // {name: 'clz', age: 19}

既然存在多个源对象合并,那么问题来了,如果多个源对象具有相同的属性时,会怎样呢?

多个源对象具有相同的属性时,会使用最后的那个属性值。实际过程就是从左往右合并对象,可以通过在目标对象上添加 set函数观察过程。

let target, source1, source2, source3;

target = {
    set job(newValue) {
        console.log(newValue)
    }
};

source1 = {
    job: {
        salary: 20,
    },
};

source2 = {
    job: "WebMaster",
};

source3 = {
    job: "Coder",
};

Object.assign(target, source1, source2, source3);

image-20220423204031530

相等判定Object.is()

ES6 之前的相等判断

console.log(+0 === -0); // true
console.log(+0 === 0); // true
console.log(-0 === 0); // true

console.log(NaN === NaN); // false
console.log(isNaN(NaN)); // true,要验证NaN的相等性需要使用isNaN

问题所在:

  1. +0、0会等于-0
  2. NaN不等于NaN,验证 NaN的相等性需要换方法:使用isNaN函数

ES6 新增Object.is(),和 ===很像,但是能更好的应对特殊情况。从下面的例子可以看出, === 本来的功能它有,还能很好的应对上面说的问题。

console.log(Object.is({}, {})); // false
console.log(Object.is("2", 2)); // false
console.log(Object.is(2, 2)); // true

console.log(Object.is(+0, -0)); // false
console.log(Object.is(+0, 0)); // true
console.log(Object.is(-0, 0)); // false

console.log(Object.is(NaN, NaN)); // true

属性

属性名简写

常用

当属性名和变量名相同时,我们可以使用简写。因为它会自动去找同名变量。如果找不到,则会报错。

const age = 21;
const person = {
    age, // 当属性名和变量名一样时,可以简写。会自动去找同名变量。如果找不到,则会报错
    // age: age
};

console.log(person);    // {age: 21}

方法算是特殊的属性,也能简写。实际上,简写版本很常见

let person = {
    // listen: function () {
    //     console.log('Euterpe')
    // }
    listen() {
        console.log("Euterpe");
    },
};

person.listen();    // Euterpe

可计算属性

引入可计算属性之前

我们现在有两个变量: nameKey ageKey。想要让它的值作为对象的属性名。

const nameKey = "name";
const ageKey = "age";

let person = {
    nameKey: 'clz',
    ageKey: 21
}
console.log(person)     // {nameKey: 'clz', ageKey: 21}

发现,结果和我们想象中的不太一样。

这个时候,如果想要实现我们想要的效果,只能够使用下标的形式,因为只有下标形式才会去找变量的值。

const nameKey = "name";
const ageKey = "age";

// let person = {}
// person.nameKey = 'clz'
// person.ageKey = 21

// console.log(person)     // {nameKey: 'clz', ageKey: 21}

let person = {};
person[nameKey] = "clz";
person[ageKey] = 21;
console.log(person);       // {name: 'clz', age: 21}

引入可计算属性之后,可以直接在对象字面量中直接动态命名属性

const nameKey = "name";
const ageKey = "age";

let person = {
  [nameKey]: "clz",
  [ageKey]: 21,
};
console.log(person); // {name: 'clz', age: 21}

简写方法名可以和可计算属性搭配使用

const methodKey = "listen";
let person = {
  [methodKey]() {
    console.log("Euterpe");
  },
};

person.listen();    // Euterpe

对象解构

常用,通过 {a} = obj的形式,从 obj中取出属性a的值,赋值给左边的a。

let person = {
  name: "clz",
  age: 21,
};

// 对象解构
const { name, age } = person;
console.log(name, age);

对象解构支持重命名, {value: newValue} = obj,不过此时, name并不会有值。

// 对象解构重命名
const { name: myname, age: myage } = person;
console.log(myname, myage);

如果解构赋值的属性不存在,那么该变量的值就是undefined

// 如果解构赋值的属性不存在,那么该变量的值就是undefined
const { job } = person;
console.log(job);        // undefined

解构赋值支持定义默认值。

// 定义默认值,当解构赋值的属性不存在时,该变量的值就是默认值
const { myjob = "Coder" } = person;
console.log(myjob);

对象解构会把原始值当成对象。nullundefined不能被解构,之前的解构赋值的属性不存在,那么该变量的值就是undefined null undefined不成立,会直接报错,如Cannot destructure property '_' of 'null' as it is null.

先声明后解构赋值

const person = {
    name: 'clz',
    age: 21
}

let name, age

{ name, age }   = person    // 报错,`Uncaught SyntaxError: Unexpected token '='`

那么,是不是不能先声明,后解构复制呢?
答案是可以的,只不过,此时赋值表达式需要包含在一对括号里

const person = {
    name: "clz",
    age: 21,
};

let name, age;

({ name, age } = person);

console.log(name, age);     // clz 21

不只是小括号可以,使用中括号也可以,不过使用花括号就会报错了,因为解构赋值就是用的花括号

解构赋值支持嵌套结构

同理,第一层不会有结果,可以打印job测试

let person = {
    job: {
        salary: 112,
    },
};

const {
    job: { salary },
} = person;
console.log(salary);    // 112

部分解构

部分解构:如果一个解构表达式多个赋值,开始的赋值成功,而中间的赋值出错的话,解构赋值开始的部分还是能完成,只是中间报错的部分以及后面的部分不能完成。

const person = {
  name: "clz",
  age: 21,
};

let personName;
let personFoo;
let personAge;

try {
  ({
    name: personName,
    // 因为personFoo没有bar属性,所以会报错
    bar: personFoo.bar,
    age: personAge,
  } = person);
} catch (e) {
  console.log(e);
}
console.log(personName, personAge, personFoo);

image-20220423211723147

参数上下文匹配

在函数参数中也可以进行解构赋值。

let person = {
    name: "clz",
    age: 27,
};

function mytest1(a, { name, age }, b) {
    console.log(a);
    console.log(name, age);
    console.log(b);
}

function mytest2({ name: myName, age: myAge }) {
    console.log(myName, myAge);
}

mytest1(1, person, 2);

console.log("%c%s", "color:red;font-size:24px;", "============");
mytest2(person);

image-20220423211842229

目录
相关文章
|
2月前
|
JavaScript 前端开发
JavaScript Date(日期) 对象
JavaScript Date(日期) 对象
53 2
|
1月前
|
JavaScript 前端开发
如何在 JavaScript 中使用 __proto__ 实现对象的继承?
使用`__proto__`实现对象继承时需要注意原型链的完整性和属性方法的正确继承,避免出现意外的行为和错误。同时,在现代JavaScript中,也可以使用`class`和`extends`关键字来实现更简洁和直观的继承语法,但理解基于`__proto__`的继承方式对于深入理解JavaScript的面向对象编程和原型链机制仍然具有重要意义。
|
1月前
|
Web App开发 JavaScript 前端开发
如何确保 Math 对象的方法在不同的 JavaScript 环境中具有一致的精度?
【10月更文挑战第29天】通过遵循标准和最佳实践、采用固定精度计算、进行全面的测试与验证、避免隐式类型转换以及持续关注和更新等方法,可以在很大程度上确保Math对象的方法在不同的JavaScript环境中具有一致的精度,从而提高代码的可靠性和可移植性。
|
1月前
|
JSON 前端开发 JavaScript
JavaScript中对象的数据拷贝
本文介绍了JavaScript中对象数据拷贝的问题及解决方案。作者首先解释了对象赋值时地址共享导致的值同步变化现象,随后提供了五种解决方法:手动复制、`Object.assign`、扩展运算符、`JSON.stringify`与`JSON.parse`组合以及自定义深拷贝函数。每种方法都有其适用场景和局限性,文章最后鼓励读者关注作者以获取更多前端知识分享。
19 1
JavaScript中对象的数据拷贝
|
1月前
|
JavaScript 前端开发 图形学
JavaScript 中 Math 对象常用方法
【10月更文挑战第29天】JavaScript中的Math对象提供了丰富多样的数学方法,涵盖了基本数学运算、幂运算、开方、随机数生成、极值获取以及三角函数等多个方面,为各种数学相关的计算和处理提供了强大的支持,是JavaScript编程中不可或缺的一部分。
|
2月前
|
存储 JavaScript 前端开发
JavaScript 对象的概念
JavaScript 对象的概念
49 4
|
2月前
|
缓存 JavaScript 前端开发
JavaScript中数组、对象等循环遍历的常用方法介绍(二)
JavaScript中数组、对象等循环遍历的常用方法介绍(二)
52 1
|
2月前
|
存储 JavaScript 前端开发
js中函数、方法、对象的区别
js中函数、方法、对象的区别
23 2
|
2月前
|
JavaScript 前端开发 Unix
Node.js 全局对象
10月更文挑战第5天
39 2
|
2月前
|
存储 JavaScript 前端开发
js中的对象
js中的对象
24 3