扩展的对象功能
属性初始化器的速记法
ES5
function aaa (name , age ) {
return {
name:name,
age:age
}
}
ES6
function aaa (name , age ){
return {
name,
age
}
}
// 当对象字面量中的属性只有名称时 js会在周边作用域查找同名的变量 找到的 该变量将会被赋给对象字面量的同名属性
方法的简写
ES5
var aaa = {
name : "zhangsan"
newname: function () {
console.log(this.name)
}
}
ES6
var aaa = {
name : "lisi"
newname() {
console.log(this.name)
}
}
需计算属性名
在ES6中需要计算属性名时对象字面量语法的一部分,它用的也是方括号表示法,在此前 在对象实例上的用法一致
var lastName = "last name"
var person = {
"first name" : "zhangsan",
[lastName] : "lisi"
}
console.log(person["first name"]) //zhangsan
console.log(person[lastName])//lisi
对象字面量内的方括号表明该属性名需要计算,结果是一个字符串 这意味着其中可以包含表达式
var cc = "name"
var person = {
["aa" + cc] : "zhangsan",
["bb" + cc] : "lisi"
}
console.log(person["aaname"])//zhangsan
console.log(person["bbname"])//lisi
Object.is()方法
在JS中比较两个值 一般会采用相等运算符()或严格相等运算符(=) 为了避免在比较时发生类型转换 多数使用后者(===)但是严格的运算符也不完全准备 它会认为+0和-0相等
ES6可以用Object.is()方法来弥补严格相等运算符残留的怪异点
这个方法接受会接受两个参数 并在两者的值相等时返回ture
console.log(+0 == -0) /* ture */
console.log(+0 === -0) /* ture */
console.log(Object.is(+0 , -0))/* fales */
console.log(NaN == NaN) /* fales */
console.log(NaN === NaN) /* fales */
console.log(Object.is(NaN , NaN)) /* ture */
console.log("5" == 5) /* ture */
console.log("5" === 5) /* fales */
console.log("5" == "5") /* ture */
console.log(Object.is("5" , 5)) /* fales */
//多种情况下 Object.is()的结果与===运算符时相同的,仅有的例外是:它会认为 +0 -0 不相等 而且NaN 等于 NaN 不过没有必要停止使用严格相等运算符 选择三者其一 需要看代码的实际情况
Object.assign()方法
Mixin : 混入
Object.keys()
var arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // console: ['0', '1', '2']
// array like object
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.keys(obj)); // console: ['0', '1', '2']
// array like object with random key ordering
var anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.keys(anObj)); // console: ['2', '7', '100']
重复的对象字面量属性
"use strict" //严格模式
var person = {
name:"zhangsan"
name:"lisi"
} //在es5严格模式语法错误
在ES5中第二个属性会造成语法错误 但ES6中移出了重复属性的检查 严格模式和非严格模式都不在检查重复的属性 当存在重复属性时 排在后面的属性的值会成为该属性的实际值
自有属性的枚举顺序
ES6中严格定义了对象有自有属性在被枚举时返回的顺序 这对Object.getOwnPropertyNames()与Reflect.ownKeys 如何返回属性造成了影响 还同样影响了Object.assign()处理属性的顺序
自有属性枚举时基本顺序如下:
1.所有的数字类型键,按升序排列
2.所有的字符串类型键,按被添加到对象的顺序排列
3.所有的符号类型键,也按添加顺序排列
var obj = {
a:1,
0:1,
b:1,
2:1,
d:1,
1:1
}
obj.c= 1
console.log(Object.getOwnPropertyNames(obj).join(""))
//012abdc
注意 数值类型的键会被合并并排序,及时这未遵循在对象字面量中的顺序 字符串类型的键会跟在数值类型的键之后 按照被添加到obj 对象的顺序 在对象 字面量中定义的键会首先出现 然后出现此后动态添加到对象的键
模块
JS“共享一切”的代码加载的方式是该语言混乱且最容易出错的方面之一。其他语言使用包(package)之类的概念来定义代码的作用域子啊ES6之前 一个应用的每个JS文件所定义的所有内容都由全局作用域共享 当web应用变的复杂需要越来越多的JS代码时 这种方式导致了诸多问题 如命名冲突 安全问题 ES6的目标就是解决这些作用域的问题
NodeJs检查对ES6支持程度
检查本地是否安装Node.js node -v
检查是否安装 taobao cnpm(包管理工具) cnpm -v
安装es-checker cnpm install -g es-checker -g是全局
检查Node.js支持es6的程度 es-checker
何为模块?
模块(Modules)是使用不同方式加载的JS文件(与JS原先的脚本加载方式相同)这种不同迷失很有必要,因为它与脚本有大大不用的语义
1.模块代码自动运行在严格模式下,并且没有任何办法跳出严格模式
2.在模块的顶级作用域创建变量,不会被自动添加到共享的全局作用域 他们只存在模板顶级作用域的内部
3.模块顶级作用域的this值为undefined
4.模块不允许在代码中使用HMTL风格的注释
5.对于需要让模块外部代码访问的内容,模块必须导出他们
6.允许模块从其他模块导入绑定
基本的导出
使用export关键字将已发布的代码部分公开给其他的模块 最简单的是 把关键字放在变量、函数、类声明前
//导出数据
export var color = "red"
export let name = "Nicholas"
export const magicNumber = 7
//导出函数
export function sum (num1 , num2){
return num1 + num2
}
//导出类
export class aaa {
constructor(length , width){
this.length = length
this.width = width
}
}
//数据 类 函数 声明前没有加export
let name = "zahngsan"
function bbb () {
bb = 10
return bb
}
//以上的目前是没有导出 的数据 类 函数
export {bbb} 等同于 export { bbb : bbb }
//所以bbb也被导出了
除了export关键字之外 每个声明都与正常形式完全一样 每个被导出的函数或者类都有名称 这是因为导出的函数声明与类声明必须要有名称。你不能使用这种语法来导出匿名函数或匿名类 除非是默认关键字default
其次 函数还可以导出引用 (即代码最后一行)
没有被导出的函数在模块外部时不可访问的 没有被显示导出的变量 函数或类都会在模块内保持私有的
基本的导入
有了包含导出的模块 就能在其他模块内使用 import关键字来访问导出的功能
import { aaa , bbb } from “./xxx.js”
在node中测试export和import
1.将文件名修改成.mjs
2.通过指令来启动文件 node --experimental-modules ./文件名.mjs 导入文件下 要有调用
导入单个绑定
import {sum} from “./xxx.js”
console.log(sum(1,2)) 在node执行打印的话(xxx.mjs)
导入多个绑定
import { sum , bbb , ccc , ddd} from “./xxx.js”
console.log(sum(1 , ddd))
console.log{bbb(1 , 2 )} 在node执行打印的话(xxx.mjs)
完全导入一个模块
export { aaa, bbb , ccc , }
将整个模块当作一个对象进行导入
import * as all ferom “./xxx.js”
all.aaa()
all.bbb()
all.ccc()
模块语法的限制
export 与 import 必须在用在其他语句或表达式的外部
if (flag) {
export flag //语法错误
}
function aaa() {
import flag from "./xxx.js"
}
导出语句不能有条件的 也不能以任何方式动态使用 因为模块语法要让JS能静态判断 导出的是什么 所以 export 必须在顶级作用域使用 (最后一行)
导入语句不能语句内部使用 所以import 必须在模块顶级作用域使用(第一行)
导入绑定的一个微妙怪异点
在ES6中导入的语句为变量、函数、类 创建了只读的绑定 不想其他变量引用了原始的绑定 导入绑定的模块无法修改绑定的值 但负责导出的模块可以修改绑定的值
export var name ="zhangsan"
export function aaa (newName) {
name = newName
}
import * as bbb grom "./xxx.js"
bbb.aaa("lisi")
console.log(bbb.name) // lisi
通过传参让name值改变
//调用aaa("lisi")会回到导出的aaa()的模块内部,并在那里执行 将name设置为lisi
//注意 这个变化会自动反映到所导入的name绑定上,这是因为绑定的name是导出的,name标识符的本地名称 二者并非同一个事物
外部导入的name变量是对于模块内部的name的只读引用 反映出name的变化 这种绑定关系不会被破坏
模块导出与导入的绑定机制 ,与写在一个文件或模块内的代码时不同的
重命名导出与导入
如果导出不想用变量、函数、类的原始名字 可以使用关键字 as 来定义新的名称
function aaa (num1, num2) {
return num1 + num2
}
export {aaa as bbb}
//这是利用as关键字修改了名称 导入函数时必须使用bbb
import {bbb} from "./xxx.js"
console.log{bbb(1,2)}
//当导入函数是 也不想用这个名称是 也可以修改
import {bbb as ccc} from "./xxx.js"
console.log{ccc(3,5)}