资讯专栏INFORMATION COLUMN

ES6(中)

dreamGong / 1314人阅读

摘要:它用来比较两个值是否严格相等,与严格比较运算符的行为基本一致。两个对象的地址不一样与严格比较运算符的不同之处只有两个一是不等于,二是等于自身基本用法方法用于对象的合并,将源对象的所有可枚举属性,赋值到目标对象。

这是ES6的入门篇教程的笔记,网址:链接描述,以下内容中粗体+斜体表示大标题,粗体是小标题,还有一些重点;斜体表示对于自身,还需要下功夫学习的内容。这里面有一些自己的见解,所以若是发现问题,欢迎指出~
上一篇es5的到最后令人崩溃,看来深层的东西还是不太熟,希望这次不要这样了!!!

对象的扩展

1、属性的简洁表示法
ES6允许直接写入变量和函数,作为对象的属性和方法,这样的书写更加简洁。

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

// 等同于
const baz = {foo: foo}; // 在对象之中,直接写变量,这时,属性名为变量名,属性值为变量值

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

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

// 等同于
const o = {
    method: function() {
        return "Hello!";
    }
};

// 一个实际的例子
let birth = "2000/01/01";
const Person = {
    name: "张三",
    birth, // 等同于 birth: birth
    hello() { console.log("我的名字是", this.name); } // 等同于hello: function ()...
};

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

2、属性名表达式
JavaScript定义对象的属性,有两种方法。

obj.foo = true; // 直接用标识符作为属性名
obj["a" + "bc"] = 123; // 用表达式作为属性名,这时要将表达式放在方括号之内

// ES6允许字面量定义对象时,用表达式作为对象的属性名,即把表达式放在**方括号**内
let propKey = "foo";
let obj = {
    [propKey]: true,
    ["a" + "bc"]: 123
};

需要注意的是,属性名表达式与简洁表示法,不能同时使用,会报错。

// 报错
const foo = "bar";
const bar = "abc";
const baz = { [foo] };

// 正确
const foo = "bar";
const baz = { [foo]: "abc" };

// 还需要注意的是,属性名表达式如果是一个对象,默认情况下会自动将对象转为字符串[object Object],这一点需要特别的小心

属性的遍历
ES6一共有5种方法可以遍历对象的属性。
(1)for...in
for...in 循环遍历对象自身和继承的可枚举属性(不含Symbol属性)。
(2)Object.keys(obj)
Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性)的键名。
(3)Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames(obj)返回一个数组,包含对象自身的所有属性(不含Symbol属性,但是包括不可枚举属性)的键名。
(4)Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有Symbol属性的键名。
(5)Reflect.ownKeys(obj)
Reflect.ownKeys返回一个数组,包含对象自身的所有键名,不管Symbol或字符串,也不管是否可枚举。

扩展运算符
如果扩展运算符后面是一个空对象,则没有任何效果。

{...{}, a: 1} // { a: 1 }

// 如果扩展运算符后面不是对象,则会自动将其转为对象
{...1} // {}

// 数组是特殊的对象,所以对象的扩展运算符也可以用于数组
let foo = { ...["a", "b", "c"] };
foo // {0: "a", 1: "b", 2: "c"  }

对象的扩展运算符等同于使用Object.assign()方法。(Object.assign方法只对顶层属性赋值,并没有继续做递归,所以它并不是真正的深拷贝。)

let aClone= { ...a };
// 等同于
let aClone = Object.assign({}, a);
对象的新增方法

1、Object.is()
ES5比较两个值是否相等,只有两个运算符:相等运算符(==)和严格相等运算符(===)。两者都有缺点,(==)会自动转换数据类型,(===)的NaN不等于自身,以及+0等于-0。JavaScript缺乏一种运算,在所有环境中,只要两个值是一样的,它们就应该相等。
ES6提出“Same-value equality”(同值相等)算法,用来解决这个问题。
Object.is就是部署这个算法的新方法。它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。

Object.is("foo", "foo"); // true
Object.is({}, {}); // false 两个对象的地址不一样

// 与严格比较运算符的不同之处只有两个:一是+0不等于-0,二是NaN等于自身
+0 === -0 // true
NaN === NaN // false

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

2、Object.assign()
基本用法
Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,赋值到目标对象(target)。
Object.assign方法的第一个参数是目标对象,后面的参数都是源对象。

const target = { a: 1, b: 1 };
const source1 = { b: 2, c: 2 }; // 目标对象与源对象有同名属性b
const source2 = { c: 3 }; // 多个源对象有同名属性

Object.assign(target, source1, source2);
target; // {a: 1, b: 2, c: 3} 后面的属性会覆盖前面的属性

// 如果参数不是对象,则会先转成对象,然后返回。
// 由于undefined和null无法转成对象,所以如果它们作为参数,就会报错。
Object.assign(undefined); // 报错
Object.assign(null); // 报错
// 如果非对象参数出现在源对象的位置(即非首参数),那么处理规则有所不同。首先,这些参数都会转成对象,如果无法转成对象,就会跳过。也就是说,如果undefined和null不在首参数,就不会报错。
let obj = {a: 1};
Object.assign(obj, undefined) === obj; // true
Object.assign(obj, null) === obj; // true

注:
(1)浅拷贝
Object.assgin方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对拷贝得到的是这个对象的引用。(对于这个深表怀疑,我觉得Object.assign并不是真正意义上的浅拷贝,其他资料说的是,对其顶层属性赋值。)
(2)同名属性的替换
对于这种嵌套的对象,一旦遇到同名属性,Object.assign的处理方法是替换,而不是添加。
(3)数组的处理
Object.assign可以用来处理数组,但是会把数组视为对象。

Object.assign([1, 2, 3], [4, 5]) // [4, 5, 3]
// 上面代码中,Object.assign把数组视为属性名为0、1、2的对象,因此源数组的0号属性4覆盖了目标数组的0号属性1。

(4)取值函数的处理
Object.assign只能进行值得赋值,如果要复制的值是一个取值函数,那么将求值后再复制。

const source = {
    get foo() { return 1}
};
const target = {};
Object.assign(target, source); // { foo: 1 }

常见用途
Object.assign方法有很多用处。
(1)为对象添加属性

class Point {
    constructor(x, y) {
        Object.assign(this, {x, y});
    }
}

(2)为对象添加方法
(3)克隆对象

function clone(origin) {
    return Object.assign({}, origin);
}

emmm,这不是深拷贝,只是对顶层属性做了赋值。。。
(4)合并多个对象
(5)为属性指定默认值

4.__proto__属性,Object.setPrototypeOf(),Object.getPrototypeOf()
JavaScript语言的对象继承是通过原型链实现的。

__proto__属性
用来读取或设置当前对象的prototype对象。目前,所有浏览器(包括IE11)都部署了这个属性。

// es5 的写法
const obj = {
    method: function() { ... }
};
obj.__proto__ = someOtherObj;

// es6 的写法
var obj = Object.create(someOtherObj);
obj.method = function() { ... };

实际上,__proto__调用的是Object.prototype.__proto__.

5.Object.keys(), Object.values(), Object.entries()
ES5引入了Object.keys方法,返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名。

var obj = { foo: "bar", baz: 42 };
Object.keys(obj);
// ["foo", "baz"]

ES2017引入了跟Object.keys配套的Object.values和Object.entries,作为遍历一个对象的补充手段,供for...of循环使用.

Object.entries()
Object.entries()方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的价值对数组。

const obj = { foo: "bar", baz: 42 };
Object.entries(obj); // [ ["foo", "bar"], ["baz", 42] ]

除了返回值不一样,该方法的行为与Object.values基本一致。

Symbol

1.概述
ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。它是JS语言的第七种数据类型,前六种是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。
Symbol值通过Symbol函数生成,也就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的Symbol类型。凡是属性名属于Symbol类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。

let s = Symbol(); // 注意,Symbol函数前不能使用new命令,否则会报错。这是因为生成的Symbol是一个原始类型的值,不是对象。
typeof s; // "symbol"

需要注意的是,Symbol函数的参数只是表示对当前Symbol值的描述,因此相同参数的Symbol函数的返回值是不相等的。

// 没有参数的情况
let s1 = Symbol();
let s2 = Symbol();
s1 === s2; // false  

// 有参数的情况
let s1 = Symbol("foo");
let s2 = Symbol("foo");
s1 === s2; // false

// Symbol值不能与其他类型的值进行运算,会报错
let sym = Symbol("My symbol");
"your symbol is " + sym; // TypeError: can"t convert symbol to string

// 但是Symbol值可以显示转为字符串。
let sym = Symbol("My symbol");
String(sym); // "Symbol(My symbol)"
sym.toString(); // "Symbol(My symbol)"

......
下面的内容就挑着看了。。。。。

// 去除数组重复成员的方法:
[...new Set(array)];

NaN == NaN; // false
let set = new Set();
let a = NaN;
let b = NaN;
set.add(a);
set.add(b);
set; // Set {NaN} 说明在Set内部,两个NaN是相等的。

set = new Set();
set.add({});
set.size; // 1
set.add({});
set.size; // 2  说明两个空对象在Set里面是不相等的。

编程风格
1、块级作用域
1)let取代var
ES6提出了两个新的声明变量的命令:let和const,其中,let完全可以取代var,因为两者的语义相同,而且let没有副作用。
2)全局常量和线程安全
在let和const之间,建议优先使用const,尤其是在全局环境,不应该设置变量,只应设置常量。
const比较符合函数式编程思想,运算不改变值,只是新建值,而且这样也有利于将来的分布式运算;并且JavaSCript编译器回对const进行优化,多使用const,有利于提高程序的运行效率,也就是说let和const的本质区别,其实是编译器内部的处理不同。

// bad 
var a = 1, b = 2, c = 3;

// good
const a = 1;
const b = 2;
const c = 3;

// best
const [a, b, c] = [1, 2, 3];

2、字符串
静态字符串一律使用单引号或反引号,不使用双引号。动态字符串使用反引号。

// bad
const a = "foobar";
const b = "foo" + a + "bar";

// acceptable
const c = `foobar`;

// good
const a = "foobar";
const b = `foo${a}bar`;

3、解构赋值
使用数组成员对变量赋值时,优先使用解构赋值。

const arr = [1, 2, 3, 4];

// bad
const first = arr[0];
const second = arr[1];

// good
const [first, second] = arr;

函数的参数如果是对象的成员,优先使用解构赋值。

// bad
function getFullName(user) {
    const firstName = user.firstName;
    const lastName = user.lastName;
}

// good
function getFullName(obj) {
    const { firstName, lastName } = obj;
}

// best
function getFullName({ firstName, lastName }) {
}

4、对象
单行定义的对象,最后一个成员不以逗号结尾。多行定义的对象,最后一个成员以逗号结尾。

// bad
const a = { k1: v1, k2: v2, };
const b = {
    k1: v1,
    k2: v2
};

// good
const a = { k1: v1, k2: v2 };
const b = {
    k1: v1,
    k2: v2
};

对象尽量静态化,一旦定义,就不得随意添加新的属性。如果添加属性可不避免,要使用Object.assign方法。

// bad
const a = {};
a.x = 3;

// if reshape unavoidable
const a = {};
Object.assign(a, { x: 3 });

// good
const a = { x: null };
a.x = 3;

如果对象的属性名是动态的,可以在创造对象的时候,使用属性表达式定义。

// bad
const obj = {
    id: 5,
    name: "San Francisco",
};
obj[getKey("enabled")] = true;

// good 
const obj = {
    id: 5,
    name: "San Francisco",
    [getKey("enabled")]: true
};

// 对象的属性和方法,尽量采用简洁表达式,这样易于描述和书写
var ref = "some value";
// bad
const atom = {
    ref: ref,
    value: 1,
    addValue: function (value) {
        return atom.value + value;
    },
};

// good
const atom = {
    ref,
    value: 1,
    addValue(value) {
        return atom.value + value;
    },
};

5、数组
使用扩展运算符(...)拷贝数组。

// bad
const len = items.length;
const itemsCopy = [];
let i ;
for(i = 0; i < len; i++) {
    itemsCopy[i] = items[i];
}

// good
const itemsCopy = [...items];

使用Array.from方法,将类似数组的对象转为数组。

const foo = document.querySelectorAll(".foo");
const nodes = Array.form(foo);

6、函数
立即执行函数可以写成箭头函数的形式。

(() => {
    console.log("Welcome to the Internet.");
})();

那些使用匿名函数当作参数的场合,尽量用箭头函数代替,因为这样更简洁,而且绑定了this。

// bad
[1, 2, 3].map(function (x) {
    return x * x;
});

// good
[1, 2, 3].map((x) => {
    return x * x;
});

// bset
[1, 2, 3].map(x => x * x);

使用默认值语法设置函数参数的默认值。

// bad
function handleThings(opts) {
    opts = opts || {};
}

// good
function handleThings(opts = {}) {}

9、模块
Module语法是JavaScript模块的标准写法。使用import取代require。

// bad
const moduleA = require("moduleA");
const func1 = moduleA.func1;
const func2 = moduleA.func2;

// good
import { func1, func2 } from "moduleA";

使用export取代module.exports。

// commonJS的写法
var React = require("react")"
var Breadcrumbs = React.createClass=({
    render() {
        return 

不要在模块输入中使用通配符。因为这样可以确保你的模块之中,有一个默认输出(export default)。

// bad
import * ad myObject from "./importModule";

// good 
import myObject from "./importModule";

如果模块默认输出一个函数,函数名的首字母应该小写;如果模块默认输出一个对象,对象名的首字母应该大写。

function makeStyleGuide() {}
export default makeStyleGuide;

const StyleGuide = {
    es6: {}
}
export default StyleGuide;

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/106807.html

相关文章

  • ES6-前世今生(0)

    摘要:更新了个版本,最新正式版是语言的下一代标准,早已在年月正式发布。基本不支持移动端浏览器对的支持情况版起便可以支持的新特性。比较通用的工具方案有,,,等。 1、ECMAScript是什么? 和 JavaScript 有着怎样的关系? 1996 年 11 月,Netscape 创造了javascript并将其提交给了标准化组织 ECMA,次年,ECMA 发布 262 号标准文件(ECMA-...

    LeviDing 评论0 收藏0
  • 给React初学者的10分钟ES6教程

    摘要:但是在中,可以通过关键字来实现类的继承的使用可以使得继承意义更加明确并且值得一提的是,如果你使用来定义的组件,那么可以在类的构造器里面,用简单的的声明方式来替代方法。 原文:The 10 min ES6 course for the beginner React Developer译者:Jim Xiao 著名的80/20定律可以用来解释React和ES6的关系。因为ES6增加了超过75...

    Awbeci 评论0 收藏0
  • ES6-7

    摘要:的翻译文档由的维护很多人说,阮老师已经有一本关于的书了入门,觉得看看这本书就足够了。前端的异步解决方案之和异步编程模式在前端开发过程中,显得越来越重要。为了让编程更美好,我们就需要引入来降低异步编程的复杂性。 JavaScript Promise 迷你书(中文版) 超详细介绍promise的gitbook,看完再不会promise...... 本书的目的是以目前还在制定中的ECMASc...

    mudiyouyou 评论0 收藏0
  • 你该知道的ES6那些事儿

    摘要:最近重构了一个项目,引入了部分用法,最大的感受是让这门语言变得更加严谨,更加方便。通过该方法获得位置后还得比较一次才能判断是否存在。再来看看的写法使用数组来初始化一个,构造器能确保不重复地使用这些值。下面提供链接,供有兴趣的朋友参考。 最近重构了一个SPA项目,引入了部分ES6用法,最大的感受是ES6让javascript这门语言变得更加严谨,更加方便。本篇将结合实战经验,对最常用的部...

    CoffeX 评论0 收藏0
  • 10个最佳ES6特性

    摘要:,正式名称是,但是这个名称更加简洁。已经不再是最新的标准,但是它已经广泛用于编程实践中。而制定了模块功能。自从年双十一正式上线,累计处理了亿错误事件,得到了金山软件等众多知名用户的认可。 译者按: 人生苦短,我用ES6。 原文: Top 10 ES6 Features Every Busy JavaScript Developer Must Know 译者: Fundebug 为了保...

    codeKK 评论0 收藏0
  • [ ES6 ] 快速掌握常用 ES6 (一)

    摘要:常量变量先说说常量和变量的概念吧,常量是说那种进行一次赋值后不会更改的值,比如说游戏账户的,变量是说赋值后有更改的需求的,比如游戏名,游戏密码。常用实例交换变量的值提取数据解构赋值对提取对象中的数据,尤其有用。 本系列文章适合快速掌握 ES6 入门语法,想深入学习 ES6 的小伙伴可以看看阮一峰老师的《ECMAScript 6 入门》 学习 20% 的知识完成 80% 的工作 关于 ...

    ispring 评论0 收藏0

发表评论

0条评论

dreamGong

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<