对象

1. ES6 允许直接写入变量和函数,作为对象的属性和方法

  • const foo = 'bar';
    
    /*****************属性的优化********************/
    const baz = {foo: foo}; // 优化为
    const baz = {foo};
    /*****************属性的优化********************/ function f(x, y) {
    return {x: x, y: y};
    }; // 优化为
    function f(x, y) {
    return {x, y};
    }; f(1, 2); // Object {x: 1, y: 2} /*****************方法的简化*******************/
    const o = {
    method: function() {
    return "Hello!";
    },
    }; // 优化为
    const o = {
    method() {
    return "Hello!";
    },
    };

2. 对象动态添加属性

obj.name = 'RyenToretto';

obj['age'] = 22;

bind方法创造的函数,name 属性返回 'bound 原函数的名字'

Function 构造函数创造的函数,name 属性返回 'anonymous'

对象的方法是一个 Symbol 值,那么name属性返回的是这个 Symbol 值的描述

  • (new Function()).name // "anonymous"
    
    var doSomething = function() {
    // ...
    };
    doSomething.bind().name; // "bound doSomething" /*****************************************************/
    const key1 = Symbol('description');
    const key2 = Symbol();
    let obj = {
    [key1]() {},
    [key2]() {},
    };
    obj[key1].name // "[description]"
    obj[key2].name // ""

3. 属性的可枚举性

对象的每个属性,都有一个属性描述对象,该对象有个 enumerable 控制属性是否可遍历

  • 有四个操作会忽略 enumerable 为 false 的属性,即不会遍历
  • for...in        只遍历对象自身的和继承的可枚举的属性。
  • Object.keys()        返回对象自身的所有可枚举的属性的键名。
  • JSON.stringify()        只串行化对象自身的可枚举的属性。
  • Object.assign()        忽略enumerable为false的属性,只拷贝对象自身的可枚举的属性。
  • ES6 规定,所有 Class 的原型的方法都是不可枚举的

Object.getOwnPropertyDescriptor(class {foo() {}}.prototype, 'foo').enumerable    // false

4. ES6 一共有 5 种方法可以遍历对象的属性名

遍历次序:

首先遍历所有数值键,按照数值升序排列。
其次遍历所有字符串键,按照加入时间升序排列。
最后遍历所有 Symbol 键,按照加入时间升序排列。

for...in

循环遍历对象自身的继承的可枚举属性(不含 Symbol 属性)

Object.keys(obj)

返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名

Object.getOwnPropertyNames(obj)

返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名

Object.getOwnPropertySymbols(obj)

返回一个数组,包含对象自身的所有 Symbol 属性的键名

Reflect.ownKeys(obj)

包含对象自身的所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举

5. super 关键字

ES6 又新增了另一个类似 this 的关键字 super,指向当前对象的原型对象

表示原型对象时只能用在对象的方法之中,用在其他地方都会报错

JavaScript 引擎内部

super.foo 等同于

  • Object.getPrototypeOf(this).foo(属性)
  • Object.getPrototypeOf(this).foo.call(this)(方法)
  • 目前,只有对象方法的简写法可以让 JavaScript 引擎确认定义的是对象的方法
  • const proto = {
    foo: 'hello',
    }; const obj = {
    foo: 'world',
    find() {
    return super.foo;
    },

    }; Object.setPrototypeOf(obj, proto);
    obj.find(); // "hello"

6. 对象的 扩展运算符 ...

回忆数组的 扩展运算符

  • const [a, ...b] = [1, 2, 3];    // 定义属性的新方式
    console.log(a); //
    console.log(b); // [2, 3]

如今对象的解构赋值

就是利用了 ...指定对象

解构赋值必须是最后一个参数,否则会报错。用于从一个对象取值,相当于将目标对

象自身的所有可遍历的(enumerable)但尚未被读取的属性和属性值,分配到 ...指定对象 上面。

所有的键和它们的值,都会拷贝到新对象上面

  • let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
    console.log(x); //
    console.log(y); //
    console.log(z); // { a: 3, b: 4 }

是浅拷贝,即 如果对象的某属性,是复合对象,则拷贝的只是一个引用地址而已

扩展运算符的解构赋值,不能复制继承自原型对象的属性

7. 对象的新增方法

Object.is() 

背景需求:

ES5 比较两个值是否相等,只有两个运算符:相等运算符(==严格相等运算符(===

它们都有缺点,== 会自动转换数据类型,=== NaN不等于自身,以及 +0 === -0

JavaScript 缺乏一种运算,在所有环境中,只要两个值是一样的,它们就应该相等。

ES6 提出“Same-value equality”(同值相等)算法,用来解决这个问题。

Object.is() 就是部署这个算法的新方法。

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

不同之处只有两个:    +0 不等于 -0    NaN 等于 NaN

  • +0 === -0    //true
    NaN === NaN // false
    Object.is(+0, -0); // false
    Object.is(NaN, NaN); // true
    Object.is('foo', 'foo'); // true
    Object.is({}, {}); // false

Object.assign()

用于对象属性的合并,将 多个源对象(source)的所有可枚举属性,复制到目标对象(target)

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

只能进行值的复制,如果要复制的值是一个取值函数,那么会执行函数,再将返回值复制过去

如果是赋值的是非取值函数,则正常复制

  • const a = {
    foo(x, y){
    console.log('哈哈');
    return "呵呵";
    },
    };
    const b = {};
    Object.assign(b, a); console.dir(b);
    console.log(b.foo());
  • 如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性(处理方法是替换,而不是添加。)
  • const target = { a: 1, b: 1 };
    
    const source1 = { b: 2, c: 2 };
    const source2 = { c: 3 }; Object.assign(target, source1, source2);
    console.log(target); // {a:1, b:2, c:3}
  • 如果非对象参数出现在源对象的位置(即非首参数),那么这些参数都会转成对象,如果无法转成对象,就会跳过
  • let obj = {a: 1};
    Object.assign(obj, undefined) === obj // true
    Object.assign(obj, null) === obj // true
  • 字符串会以数组形式,拷贝入目标对象,其他值都不会产生效果(undefined,null,number,boolean)
  • const v1 = 'abc';
    const v2 = true; // 被忽略
    const v3 = 10; // 被忽略 const obj = Object.assign({}, v1, v2, v3);
    console.log(obj); // { "0": "a", "1": "b", "2": "c" }
  • 布尔值、数值、字符串分别转成对应的包装对象时

可以看到它们的原始值都在包装对象的内部属性[[PrimitiveValue]]上面,

这个 内部属性[[PrimitiveValue]] 属性是不会被 Object.assign() 拷贝的

  • Object(true);    // {[[PrimitiveValue]]: true}
    Object(10); // {[[PrimitiveValue]]: 10}
    Object('abc'); // {0: "a", 1: "b", 2: "c", length: 3, [[PrimitiveValue]]: "abc"}
  • 不拷贝 不可枚举的属性(enumerable: false)
  • 属性名为 Symbol 值的属性,也会被 Object.assign() 拷贝

注意:

Object.assign() 实行的是浅拷贝,而不是深拷贝。

也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用

  • Object.assign() 可以用来处理数组,但是会把数组视为对象
  • Object.assign([1, 2, 3], [4, 5]);    // [4, 5, 3]

常见用途

  • ① 为对象添加属性
  • class Point {
    constructor(x, y) {
    Object.assign(this, {x, y}); // 将 x 属性 和 y 属性 添加到 Point类 的对象实例
    };
    };
  • ② 为对象 添加方法
  • Object.assign(Point.prototype, {
    someMethod(arg1, arg2) {
    ···
    },
    anotherMethod() {
    ···
    },
    });
  • ③ 克隆对象
  • 只克隆 原始对象 本身的值
  • function clone(origin) {
    return Object.assign({}, origin);
    };
  • 克隆,并克隆其原型链
  • function clone(origin) {
    let originProto = Object.getPrototypeOf(origin);
    return Object.assign(Object.create(originProto), origin);
    };
  • ④ 合并多个对象
  • const merge = (target, ...sources) => Object.assign(target, ...sources);
    
    const newObj = merge({}, obj1, obj2, obj3);
  • ⑤ 为属性指定默认值
  • const DEFAULTS = {
    logLevel: 0,
    outputFormat: 'html'
    }; function processContent(options) {
    options = Object.assign({}, DEFAULTS, options);
    console.log(options);
    // ...
    };
  • 注意,由于存在浅拷贝的问题
  • const DEFAULTS = {
    url: {
    host: 'example.com',
    port: 7070
    },
    }; processContent({ url: {port: 8000} })
    // {
    // url: {port: 8000} // 由于拷贝了整个对象,所以覆盖了原来的 url 对象,导致对象里的内容不一样
    // }

Object.getOwnPropertyDescriptors()

ES6 引入了 Object.getOwnPropertyDescriptors() 返回指定对象所有自身属性(非继承属性)的描述对象

是为了解决 Object.assign() 无法正确拷贝 get 属性 和 set 属性 的问题

Object.assign() 总是拷贝一个属性的值,而不会拷贝它背后的赋值方法取值方法

  • const obj = {
    foo: 123,
    get bar() { return 'abc' },
    }; Object.getOwnPropertyDescriptors(obj)
    // { foo:
    // { value: 123,
    // writable: true,
    // enumerable: true,
    // configurable: true },
    // bar:
    // { get: [Function: get bar],
    // set: undefined,
    // enumerable: true,
    // configurable: true } }

读写当前对象的 原型对象

ES5 指定原型对象,是通过 隐式原型属性 __proto__

__proto__前后的双下划线,说明它本质上是一个内部属性,而

不是一个正式的对外的 API,只是由于浏览器广泛支持,才被加入了 ES6。

ES6 标准明确规定,只有浏览器必须部署这个属性,其他运行环境不一定需要部署,而且新的代码最好认为这个属性是不存在的

因此,无论从语义的角度,还是从兼容性的角度,都应该使用下面的 方法 代替

Object.setPrototypeOf()(写操作)

Object.getPrototypeOf()(读操作)

Object.create()(生成操作)

Object.keys()

ES5 引入了 Object.keys(),返回一个数组

成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名

Object.values

返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值

Object.entries

返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组

  • let obj = { one: 1, two: 2 };
    for (let [k, v] of Object.entries(obj)) {
    console.log(
    `${JSON.stringify(k)}: ${JSON.stringify(v)}`
    );
    };
    // "one": 1
    // "two": 2

Object.fromEntries()

返回一个对象,是Object.entries()的逆操作,用于将一个 键值对数组 转为 对象

  • Object.fromEntries([
    ['foo', 'bar'],
    ['baz', 42]
    ]);
    // { foo: "bar", baz: 42 }
  • 配合URLSearchParams对象,将查询字符串转为对象
  • Object.fromEntries(new URLSearchParams('foo=bar&baz=qux'))
    // { foo: "bar", baz: "qux" }
  • 主要目的,是将 键值对的数据结构 还原为对象,因此特别适合将 Map 结构转为对象。
  • // 例一
    const entries = new Map([
    ['foo', 'bar'],
    ['baz', 42]
    ]); Object.fromEntries(entries); // { foo: "bar", baz: 42 } // 例二
    const map = new Map().set('foo', true).set('bar', false);
    Object.fromEntries(map); // { foo: true, bar: false }

ECMA Script 6_对象的扩展的更多相关文章

  1. ECMA Script 6_数值的扩展

    1. 二进制 和 八进制 新的表示法 前缀 0b(或0B) 表示 二进制 前缀 0o(或 0O )表示 八进制 console.log(0b111110111 === 503); // true co ...

  2. ECMA Script 6_数组的扩展_扩展运算符

    1. 扩展运算符 内部调用的是数据结构的 Iterator 接口, 因此只要具有 Iterator 接口的对象,都可以使用扩展运算符 ... 如 map,,,, [...arr] 扩展运算符(spre ...

  3. ECMA Script 6_字符串_扩展_字符 是4字节还是2字节?_模板字符串

    ES6 字符串扩展 ES6 加强了对 Unicode 的支持,并且扩展了字符串对象 字符 的 Unicode 表示法 允许采用 \uxxxx 形式表示一个字符, 其中 xxxx 表示字符的 Unico ...

  4. ECMA Script 6_函数的扩展

    ES6规定只要函数参数使用了默认值.解构赋值.或者扩展运算符, 那么函数内部就不能显式设定为严格模式,否则会报错 1. 参数的默认值 ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面 函数 ...

  5. ECMA Script 6_简单介绍

    ECMAScript 6 ECMA 组织 前身是 欧洲计算机制造商协会 指定和发布脚本语言规范,标准在每年的 6 月份正式发布一次,作为当年的正式版本 这样一来,就不需要以前的版本号了,只要用年份标记 ...

  6. ECMA Script 6_唯一容器 Set_映射容器 Map

    唯一容器 Set ES6 提供了新的数据结构 Set Set 结构没有键名,只有键值(或者说 键名 和 键值 是同一个值) 它类似于数组,但是成员的值都是唯一的,没有重复的值 Set 内部判断两个值是 ...

  7. ECMA Script 6_模块加载方案 ES6 Module 模块语法_import_export

    1. 模块加载方案 commonJS 背景: 历史上,JavaScript 一直没有模块(module)体系, 无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来. 其他语言都有这项功能: ...

  8. ECMA Script 6_异步编程之 Promise

    Promise 对象 异步编程 方案,已同步的方式表达异步的代码,解决回调地狱的问题 比传统的解决方案——回调函数和事件——更合理和更强大 是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步 ...

  9. ECMA Script 6_必须要知道的基础

    ES6 为了保持兼容性,var 命令和 function 命令声明的全局变量,依旧是顶层对象的属性: 另一方面规定,let 命令.const 命令.class 命令声明的全局变量,不属于 window ...

随机推荐

  1. Angular记录(2)

    文档资料 箭头函数--MDN:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_fun ...

  2. 第十二节:Lambda、linq、SQL的相爱相杀(1)

    一. 谈情怀  Lambda.Linq.SQL伴随着我的开发一年又一年,但它们三者并没有此消彼长,各自占有这一定的比重,起着不可替代的作用. 相信我们最先接触的应该就是SQL了,凡是科班出身的人,大学 ...

  3. 数据结构Java实现03----栈:顺序栈和链式堆栈

    一.堆栈的基本概念: 堆栈(也简称作栈)是一种特殊的线性表,堆栈的数据元素以及数据元素间的逻辑关系和线性表完全相同,其差别是线性表允许在任意位置进行插入和删除操作,而堆栈只允许在固定一端进行插入和删除 ...

  4. JGUI源码:解决手机端点击出现半透明阴影(4)

    下面开始进入正题,问题发现与解决 1.According解决手机浏览器点击出现半透明阴影 手机下点击有白色蒙版,原始效果如下,看起来很不协调 2.解决办法:增加 -webkit-tap-highlig ...

  5. 分享一个jsonp劫持造成的新浪某社区CSRF蠕虫

    最近jsonp很火,实话说已经是被玩烂了的,只是一直没有受到大家的重视.正好在上个月,我挖过一个由于jsonp造成的新浪某社区CSRF,当时是为了准备一篇文章,之后这篇文章也会拿出来分享. 因为新浪已 ...

  6. Django 内置分页器

    先导入Django内置的分页器 在商品列表页或者购物车列表页导入 在渲染list.html导入 然后在views后台渲染方法写入 打开list页面结果

  7. 简易解说拉格朗日对偶(Lagrange duality)

    引言:尝试用最简单易懂的描述解释清楚机器学习中会用到的拉格朗日对偶性知识,非科班出身,如有数学专业博友,望多提意见! 1.原始问题 假设是定义在上的连续可微函数(为什么要求连续可微呢,后面再说,这里不 ...

  8. Pytorch 常用函数

    1. torch.renorm(input, p, dim, maxnorm, out=None) → Tensor Returns a tensor where each sub-tensor of ...

  9. CKEditor5 + vue2.0 自定义图片上传、highlight、字体等用法

    因业务需求,要在 vue2.0 的项目里使用富文本编辑器,经过调研多个编辑器,CKEditor5 支持 vue,遂采用.因 CKEditor5 文档比较少,此处记录下引用和一些基本用法. CKEdit ...

  10. Visual Studio 2015中 没有“安装和部署”的解决方法

    使用Visual Studio 2015 Community新建项目,在已安装模板中的“其它项目类型”下未找到“安装和部署”选项.在微软官网下载 Microsoft Visual Studio 201 ...