ECMAScript
简介
- 它是一种由ECMA组织(前身为欧洲计算机制造商协会)制定和发布的脚本语言规范
- 而我们学的JavaScript是ECMA的实现, 但术语ECMAScript和JavaScript平时表达同一个意思
- JS包含三个部分:
ECMAScript(核心)
-
浏览器端扩展
- DOM(文档对象模型)
- BOM(浏览器对象模型)
-
服务器端扩展
Node
- ES的几个重要版本
- ES5 : 09年发布
- ES6(ES2015) : 15年发布, 也称为ECMA2015
- ES7(ES2016) : 16年发布, 也称为ECMA2016 (变化不大)
- 扩展学习参考:
- ES5 :
- http://www.zhangxinxu.com/wordpress/2012/01/introducing-ecmascript-5-1/
- http://www.ibm.com/developerworks/cn/web/wa-ecma262/
- ES6
- http://es6.ruanyifeng.com/
- ES7
- http://www.w3ctech.com/topic/1614
- ES5 :
严格模式("use strict")
- 运行模式:
- 正常(混杂)模式
- 严格模式
- 应用上严格式:
-
'strict mode'
;
-
- 作用:
- 使得
Javascript
在更严格的条件下运行 - 消除
Javascript
语法的一些不合理、不严谨之处,减少一些怪异行为 - 消除代码运行的一些不安全之处,保证代码运行的安全
- 使得
- 需要记住的几个变化
- 声明定义变量必须用
var
- 禁止自定义的函数中的this关键字指向全局对象
- 创建
eval
作用域,更安全 - 对象不能有重名属性
- 声明定义变量必须用
ES5 常用方法
JSON对象
- 作用: 用于在
json
对象/数组与js
对象/数组相互转换 -
JSON.stringify(obj/arr)
js对象(数组)转换为json对象(数组) -
JSON.parse(json)
json
对象(数组)转换为js
对象(数组)
Object扩展
-
Object.create(object, prototype[descriptors])
:- 创建一个新的对象
- 以指定对象为原型创建新的对象
- 指定新的属性, 并对属性进行描述
- 创建一个新的对象
var o = {
username: 'xiaoming',
age: 20
};
var obj = Object.create(o, {
sex: {
value: '男',//指定值
writable: true,//标识当前属性值是否是可修改的, 默认为false
configurable: true,//标识当前属性值是否是可以被删除, 默认为false
enumerable: true //标识当前属性能否用 for in 枚举,默认为false
}
});
-
Object.defineProperties(object, descriptors)
:- 为指定对象定义扩展多个属性
- get方法 : 用来获取当前属性值的回调函数
- set方法 : 用来监视当前属性值变化的回调函数,实参即为修改后的值
- 存取器属性: setter,getter 一个用来存值,一个用来取值
var o = {
firstName: 'Xiaoming',
lastName: 'Wang'
};
var obj = Object.defineProperties(o, {
fullName: {
get: function () {//获取扩展属性的值,获取拓展属性值是get方法自动调用(惰性求值)
return this.firstName + ' ' + this.lastName;
},
set: function (data) {//监听扩展属性,当扩展属性发生变化的时候自动调用
var names = data.split(' ');
this.firstName = names[0];
this.lastName = names[1];
}
}
});
- 对象本身就有 get 和 set 方法:
var obj = {
firstName: 'Xiaoming',
lastName: 'Wang',
get fullName() {//get 获取的值不能直接obj.fullName修改
return this.firstName + ' ' + this.lastName;
},
set fullName(data) {
var names = data.split(' ');
this.firstName = names[0];
this.lastName = names[1];
}
};
ES6 常用语法
2个新的关键字
let
- 声明一个变量
- 在块级作用域内有效
- 不能重复声明
- 不会预处理,不存在变量提升
const
- 定义一个常量
- 不能修改
- 其他同 let
变量的解构赋值
- 从对象或数组中提取数据,并赋值给多个变量
- 数据源:
- 对象
let {a, b} = {a: "a", b: "b"}
- 数组
let [a, b] = ['a', 'b']
- 对象
let o = {
firstName: 'Xiaoming',
lastName: 'Wang'
};
//解构对象必须以对象形式解构
//必须赋值对象已有属性
let {firstName, lastName} = o;
console.log(firstName, lastName);//Xiaoming Wang
let arr = [1, 'a', true];
//解构数组必须以数组形式解构
//根据数组下标取值,不需要的则以逗号占位
let [, a, b, c] = arr;
console.log(a, b, c);//a true undefined
let [d, ...e] = arr;
console.log(d, e);//1 ["a", true]
function fun ({firstName, lastName}) {//{firstName, lastName} = o
console.log(firstName, lastName);//Xiaoming Wang
}
各种数据类型的扩展
-
字符串
- 模板字符串
- 作用: 简化字符串的拼接
- 模板字符串必须用
``
- 变化的部分使用
${xxx}
定义
-
contains(str)
: 判断是否包含指定的字符串 -
startsWith(str)
: 判断是否以指定字符串开头 -
endsWith(str)
: 判断是否以指定字符串结尾 -
repeat(count)
: 重复指定次数
- 模板字符串
-
对象
- 简化的对象写法
let name = 'Tom'; let age = 12; let person = { name,//同名属性可以省略不写 name: name age, setName (name) { this.name = name; } };
- Object.assign(target, source1, source2..) : 将源对象的属性复制到目标对象上
- Object.is(v1, v2) : 判断2个数据是否完全相等
- proto属性 : 隐式原型属性
- 简化的对象写法
-
数组
-
Array.from(v)
: 将伪数组对象或可遍历对象转换为真数组 -
Array.of(v1, v2, v3)
: 将一系列值转换成数组 -
find(function(value, index, arr){return true})
: 找出第一个满足条件返回true的元素 -
findIndex(function(value, index, arr){return true})
: 找出第一个满足条件返回true的元素下标
-
-
函数
-
箭头函数
- 用来定义匿名函数
- 基本语法:
- 没有参数:
() => console.log('xxxx')
- 一个参数:
i => i+2
- 大于一个参数:
(i, j) => i+j
- 函数体不用大括号: 默认返回结果
- 函数体如果有多个语句, 需要用
{}
包围 - 箭头函数的
this
不是调用时决定的,而是在定义的时候处在的对象就是它的this
- 箭头函数的
this
看外层是否有函数,有,则其this
为外层函数的this
;没有,则其this
为window
- 没有参数:
- 使用场景: 多用来定义回调函数
-
形参的默认值
- 定义形参时指定其默认的值
function Point (x = 0, y = 0) { this.x = x; this.y = y; } let point = new Point(21, 22);//Point {x: 21, y: 22} let oPoint = new Point();//Point {x: 0, y: 0}
-
rest(可变)参数
- 通过形参左侧的
...
来表达, 取代arguments
的使用
function fun (a, ...values) {//...values只能放在最后 values.forEach((i, v) => {//values是一个真数组 console.log(i, v) }); }
- 通过形参左侧的
-
扩展运算符(
...
)- 可以分解出数组或对象中的数据
let arr = [2, 3, 4, 5, 6]; arr1 = [1, ...arr, 7]; console.log(arr1);//[1, 2, 3, 4, 5, 6, 7]
-
set/Map容器结构
容器: 能保存多个数据的对象, 同时必须具备操作内部数据的方法
任意对象都可以作为容器使用, 但有的对象不太适合作为容器使用(如函数)
Set的特点: 保存多个
value
,value
是不重复( 数组元素去重)Map的特点: 保存多个
key-value
,key
是不重复,value
是可以重复的-
API
-
Set
容器 : 无序不可重复的多个value
的集合体-
Set()/Set(arr)
//arr
是一维数组add(value)
delete(value)
has(value)
clear()
size
- 将
set
转化为数组:[...set]
- ``Array.from(set)`
- 数组去重:
Array.from(new Set(arr));
-
-
Map
容器 : 无序的key
不重复的多个key-value
的集合体-
Map()/Map(arr)
//arr
是二维数组set(key, value)
get(key)
delete(key)
has(key)
clear()
size
-
-
Promise
解决
回调地狱
(回调函数的层层嵌套, 编码是不断向右扩展, 阅读性很差)能以同步编码的方式实现异步调用
在
ES6
之前原生的js
中是没这种实现的, 一些第三方框架(jQuery
)实现了promise
Promise
是一个构造函数,用来生成promise
实例-
存在三个状态
-
pending
:初始化状态 -
fullfilled
:成功状态 -
rejected
:失败状态
-
-
ES6
中定义实现API
:function getDatas (url) { //初始化 promise 状态: pending //执行异步操作 //创建 xmlHttp 实例对象 let promise = new Promise((res, rej) => { let xhr = new XMLHttpRequest(); //绑定监听 xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === 200) {//请求成功,调用成功的回调 res(xhr.responseText); } else {//请求失败,调用失败的回调 rej(error); } } }; //设置请求方式及url xhr.open('GET', url) }); return promise; } //调用 getDatas('http://localhost:8080/datas') .then((data) => { console.log(data); }, (error) => { console.log(error); });
Symbol
概念:
ES6
中的添加了一种原始数据类型symbol
特点:
-
Symbol
属性对应的值是唯一的,解决命名冲突问题 -
Symbol
值不能与其他数据进行计算,包括同字符串拼串 -
for in
,for of
遍历时不会遍历symbol
属性。
使用:
-
调用
Symbol
函数得到symbol
值let symbol = Symbol(); let obj = {}; obj[symbol] = 'hello'; console.log(obj);//{Symbol(): "hello"}
-
传参标识
let symbol = Symbol('one'); let symbol2 = Symbol('two'); console.log(symbol);// Symbol('one') console.log(symbol2);// Symbol('two')
-
内置
Symbol
值除了定义自己使用的
Symbol
值以外,ES6
还提供了11个内置的Symbol
值,指向语言内部使用的方法 -
Symbol.iterator
- 对象的Symbol.iterator属性,指向该对象的默认遍历器方法
let targetData = { //等同于在指定的数据内结构上部署了 iterator 接口 //当 for of 去遍历某一个数据结构的时候,首先去找 Symbol.iterator [Symbol.iterator]: function () { let nextIndex = 0, len = this.length; return {//遍历器对象 next: function () { return { value: this[nextIndex++], done: nextIndex < len ? false : true } } } } }
iterator
概念:
iterator
是一种接口机制,为各种不同的数据结构提供统一的访问机制。
作用:
- 为各种数据结构,提供一个统一的、简便的访问接口
- 使得数据结构的成员能够按某种次序排列
-
ES6
创造了一种新的遍历命令for of
循环,iterator
接口主要供for of
消费。
工作原理:
- 创建一个指针对象(遍历器对象),指向数据结构的起始位置
- 第一次调用
next
方法,指针自动指向数据结构的第一个成员 - 接下来不断调用next`方法,指针会一直往后移动,直到指向最后一个成员
- 每调用
next
方法返回的是一个包含value
和done
的对象,{value: 当前成员的值,done: 布尔值}
-
value
表示当前成员的值,done
对应的布尔值表示当前的数据的结构是否遍历结束 - 当遍历结束的时候返回的
value
值是undefined
,done
值为false
//模拟指针对象(遍历器对象)
function myIterator (arr) {//iterator接口
let nextIndex = 0,
len = arr.length;
return {//遍历器对象
next: function () {
return {
value: arr[nextIndex++],
done: nextIndex < len ? false : true
}
}
}
}
//准备一个数据
let arr = [1, 2, 23, 'abc'];
let iteratorObj = myIterator(arr);
原生具备iterator
接口的数据(可用for of
遍历)
- Array
let arr = [1, 2, 23, 'abc'];
for(let i of arr) {
console.log(i);
}
- arguments
function fun () {
for(let i of arguments) {
console.log(i);
}
}
fun(1, 2, 23, 'abc');
- set容器
- map容器
- String
其他:
- 对象不具备
iterator
接口,故不可用for of
遍历
var o = {
username: 'Tom',
age: 23
}
for (let i of o) {
console.log(i);//Uncaught TypeError: o is not iterable
}
//添加遍历器
o[Symbol.iterator] = function* test() {
yield 1
}
for (let i of o) {
console.log(i);//1
}
- 使用三点运算符、结构赋值,默认调用
iterator
接口
for--of循环
- 遍历数组
- 遍历Set
- 遍历Map
- 遍历字符串
- 遍历伪数组
Generator
概念:
-
ES6
提供的解决异步编程的方案之一 -
Generator
函数是一个状态机,内部封装了不同状态的数据,用来生成遍历器对象 - 可暂停函数(惰性求值),
yield
可暂停,next
方法可启动。每次返回的是yield
后的表达式结果
特点:
-
function
与函数名之间有一个星号 - 内部用
yield
表达式来定义不同的状态
function* generatorExample(){
yield 'hello'; // 状态值为hello
yield 'generator'; // 状态值为generator
return "result"
}
let a = generatorExample();
a.next();//{value: "hello", done: false}
a.next();//{value: "generator", done: false}
a.next();//{value: "result", done: true},有 return 返回值则为返回值,无返回值为 undefined
a.next();//{value: undefined, done: true}
-
Generator
函数返回的是指针对象(iterator
),而不会执行函数内部逻辑 - 调用
next
方法函数内部逻辑开始执行,遇到yield
表达式停止,返回{value: yield后的表达式结果/undefined, done: false/true}
- 再次调用
next
方法会从上一次停止时的yield
处开始,直到最后 -
yield
语句返回结果通常为undefined
, 当调用next
方法时传参内容会作为启动时yield
语句的返回值。
function* generatorExample(){
let a = yield 'hello'; // 状态值为hello
console.log(a);//a的值为 undefined
yield 'generator'; // 状态值为generator
}
let a = generatorExample();
a.next();//{value: "hello", done: false}
a.next("para");//a的值变为传入的 ‘para’;//{value: generator, done: true}
class类
- 用
class
定义一类 - 用
constructor()
定义构造方法(相当于构造函数) - 一般方法:
xxx () {}
//定义父类
class Person {
//类的构造方法
constructor(name, age) {
this.name = name;
this.age = age;
}
//类的一般方法
showInfo() {
console.log(this.name, this.age);
}
}
let person = new Person('Tom', 23);
console.log(person);//Person {name: "Tom", age: 23}
person.showInfo();//Tom 23
用
extends
来定义子类用
super()
来父类的构造方法子类方法自定义: 将从父类中继承来的方法重新实现一遍
js
中没有方法重载(方法名相同, 但参数不同)的语法
//定义子类
class SubPerson extends Person {
constructor(name, age, salary) {
super(name, age);//调用父类的构造方法
this.salary = salary;
}
//重写父类的方法
showInfo() {
console.log(this.name, this.age, this.salary);
}
}
let sub = new SubPerson('Jack', 13, 10000);
console.log(sub);//SubPerson {name: "Jack", age: 13, salary: 10000}
sub.showInfo();//Jack 13 10000
ES7
async函数(源自ES2017)
概念:
真正意义上去解决异步回调的问题,同步流程表达异步操作
本质:
`Generator`的语法糖
语法:
async function asyncFun(){
let result = await Promise.resolve('success');
console.log(result);//success,如果 Promise.resolve 未传参数则为 undefined
result = await Promise.reject('fail');
console.log(result);//Uncaught (in promise) fail
}
asyncFun();
特点:
- 不需要像
Generator
去调用next
方法,遇到await
等待,当前的异步操作完成就往下执行 - 返回的总是
Promise
对象,可以用then
方法进行下一步操作 -
async
取代Generator
函数的星号*
,await
取代Generator
的yield
- 语意上更为明确,使用简单