es基础
简介
es 与 js 的关系就是,前者是后者的规范,后者是前者的一种实现
环境配置
nodejs
nodejs 的下载安装与一般的软件无异,从官网找到并且下载安装就好
npm
需要使用镜像下载: 镜像地址
直接在终端执行下列命令就可完成安装
1 | npm install -g cnpm --registry=https://npmmirror.com/ |
语法
let关键字
特点
- 声明的变量只在当前的代码块中有效
- 不满足变量提升,也就是必须在声明之后使用变量,不然会报错
- 不允许重复声明同一个变量
1 | { |
const关键字
特点
- 声明之后变量不可改变
- 声明时必须初始化
- 不满足变量提升,也就是必须在声明之后使用变量,不然会报错
- 只在当前的代码块中有效
- 不允许重复声明同一个变量
1 | const a = 1; |
变量解构赋值
解构可以用于对象,也可以很方便的将现有的对象的方法赋值到某个变量,对象的顺序没有要求,但是必须与属性同名才能得到正确的值
1 | var {age, name} = {name:"1", age:10}; |
字符串扩展
- 在 es6 中增加了字符串对
unicode
字符码的支持,可以在代码中使用\uxxx
来表示一个字符unicode
码即统一码,是计算机科学领域里的一项业界标准,包括字符集,编码方案等,unicode
是为了解决传统的字符编码方案的局限而产生的,为每种语言的每个字符都设定了统一并且唯一的二进制编码
- 利用
for...of
语句实现字符串的遍历 - 模板字符串,是增强版的字符串,使用反引号 ` 标记,可以当作普通字符串使用,也可用来定义多行字符串,或者在字符串中嵌入变量
include()
表示字符串中是否包含参数字符串,返回布尔值,支持第二个参数,表示开始搜索的位置,默认为0srartsWith()
返回布尔值,表示字符串是否以参数字符串开头,同上endsWith()
返回布尔值,表示字符串是否以参数字符串结尾,同上repeat()
返回一个由源字符串重复n
次的字符串padStart()
如果不够指定长度,在头部补全padEnd()
如果不够指定长度,在尾部补全trimStart()
消除字符串头部的空格,返回新字符串,不改变源字符串trimEnd()
消除字符串头部的空格,同上at()
返回指定位置的字符,支持负索引
数组扩展
- 扩展运算符,三个点,将一个数组转为用逗号分割的参数序列
- 将数组转为函数的参数,不需要再使用
apply
方法了 - 作为合并数组的新写法
- 将数组转为函数的参数,不需要再使用
Array.from()
用于将类数组转为真正的数组,常见类数组有三种- arguments
- 元素集合
- 类似数组的对象,但是书写要求较高,有严格的标准
Array.of()
将一组数值转为数组
对象扩展
- es6 允许再大括号内,直接写入变量和函数,作为对象的属性和方法,用于函数的返回值
- 属性名表达式,允许字面量定义对象,用表达式作为对象的属性名,就是把标达式放在括号内
- 对象的扩展运算符,三个点,相当于将对象展开
函数扩展
- 箭头函数,es6 允许使用箭头
=>
定义函数- 箭头函数如果不需要参数或者需要多个参数,就使用一个圆括号代表参数部分
- 如果箭头函数的代码块部分多于一条语句,就使用大括号将它们括起来,使用
return
返回 - 箭头函数的作用就是简化回调函数
- 对于普通函数,内部的
this
指向函数运行时所在的对象,但是对于箭头函数,内部的this
就是定义时上层作用域中的this
,箭头函数没有自己的this
只能调用上层的this
Set
- es6 提供了新的数据结构
Set
,类似于数组,但是成员的数值是唯一的,没有重复的值 Set
本身是一个构造函数,用来生成Set
数据结构- 通过
add
方法加入成员,而且Set
不会添加重复的值 - 可以接收一个数组作为参数
- 可以用作数组去除重复项的方法
- 字符串去除重复字符
- 加入值时,数据类型不会发生转换,所以字符和数字是会分别的
size
返回实例的成员总数add()
添加元素delete()
删除某个值,返回一个布尔值,表示删除操作是否成功has()
是否有某个元素clear()
清除所有元素
promise
是异步编程的一种解决办法, Promise
是一个对象,从它可以获取异步操作的消息
有三种 promise
状态,除了异步操作的结果,任何其他操作都无法改变这个状态,只有从 pending
变为 fulfilled
和从 pending
变为 rejected
的状态改变。只要处于 fulfilled
和 rejected
,状态就不会再变了即 resolved
pending
进行中fulfilled
已成功rejected
已失败
缺点
- 无法取消
Promise
,一旦新建它就会立即执行,无法中途取消 - 如果不设置回调函数,
Promise
内部抛出的错误,不会反应到外部 - 当处于
pending
状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)
then方法
- 接收两个函数作为参数,第一个参数是
Promise
执行成功时的回调,第二个参数是Promise
执行失败时的回调,两个函数只会有一个被调用 - 当事件队列的当前运行完成之前,回调函数永不会被调用,
then
方法可以返回值作为下一个链式反应的值- 当忘记返回值时,对应链条被打破,导致之后的链式反应与当前链式反应同时进行
- 大多数浏览器中不能终止的
Promise
链里的rejection
,建议后面都跟上.catch(error => console.log(error));
Async函数
使得异步操作更方便,可以把异步操作变为同步操作,但是需要使用 await
关键字来等待异步操作完成,以此来实现同步
类的使用
js
中,生成实例对象的传统方法是通过构造函数来实现,在 es6
中引入了 class
,通过这个关键字可以定义类
- 实例化需要使用
new
来实现 - 类不存在提升,也就是只能在声明之后使用
实例的属性
是指类的对象实例可以调用的属性,一般就是在构造函数中所声明并且定义的属性
静态方法
所有在类中定义的方法都会被实例继承,但是对于 static
方法不会被实例继承,但是可以直接调用,而实例中却没有此方法,如果静态方法中包含 this
那这个就是指这个类,而不是实例
静态属性
就是 class
本身的属性,也就是 Class.propname
,这个可以在类之外定义,但是不会被实例继承
module语法
js
没有将一个大的程序拆分成一些相互有依赖关系的小文件,再用简单的方式拼接起来,但是在 es6
中引入了 module
方法来实现此功能
先通过 export
指令显示指定来自外部的代码,再通过 import
命令输入
1 | export var hello = "hello"; |
测试需要采用 Nodejs
的方式测试 module
语法
Generator函数
Generator
函数有两个区分于普通函数的部分
- 在
function
之后,函数名之前有个*
- 函数内部有
yield
表达式,用yield
来定义函数内部的状态
1 | function *func() { |
执行机制
调用 Generator
函数和调用普通函数一样,在函数名后加上 ()
即可,但是该函数不会像普通函数一样立即执行,而是返回一个指向内部状态的指针,所以要调用遍历器对象 iterator
的 next
方法,指针就会从函数头部或者上一次停下来的地方开始执行,类似于 python
中的生成器函数,每调用一次都会执行到下一个 yield
或者 return
1 | func.next(); // 'one' value='1' |
需要注意的是,如果获取 yield
的值,那每一步 yield
之后,执行下一次这个参数会变成 undefined
,但是如果使用 next
传参的话,这个数据就会被附上值,总之有点复杂,可以直接看运行结果
1 | function *func() { |
除了使用 next
遍历该函数,还可以使用 for...of
来实现遍历
1 | var f3 = func(); |
return方法
返回给定值,并且结束遍历 Generator
函数
提供参数时返回该参数,不提供参数时,返回 undefined
错误处理
对于下列 Generator
函数
1 | var func2 = function* () { |
遍历器对象会抛出两个错误,第一个被 Generator
函数内部捕获,另一个因为函数体内部的 catch
函数已经执行过了,不会再捕获这个错误,所以这个错误就抛出 Generator
函数体,被函数体外的 catch
捕获
yield*表达式
yield*
表达式表示 yield
返回一个遍历器对象,用于在 Generator
函数内部,调用另一个 Generator
函数
1 | function* callee() { |
Reflext与Proxy
Proxy
可以对目标对象的读取、函数调用等操作进行拦截,然后进行操作处理。它不直接操作对象,而是像代理模式,通过对象的代理对象进行操作,在进行这些操作时,可以添加一些需要的额外操作。Reflect
可以用于获取目标对象的行为,它与Object
类似,但是更易读,为操作对象提供了一种更优雅的方式。它的方法与Proxy
是对应的Reflect
对象的方法与Proxy
对象的方法是一一对应的。所以Proxy
对象的方法可以通过调用Reflect
对象的方法获取默认行为,然后进行额外操作
Proxy
一个 Proxy
对象由两个部分组成: target
和 handler
。在通过 Proxy
构造函数生成实例对象时,需要提供这两个参数。 target
即目标对象, handler
是一个对象,声明了代理 target
的指定行为
1 | let target = { |
target
可以为空对象handler
对象也可以为空,相当于不设置拦截操作,直接访问目标对象- 通过构造函数新建实例时其实是对目标对象进行了浅拷贝,因此目标对象与代理对象会互相影响
实例方法
get(target, propKey, receiver)
用于target
对象上的propKey
的读取操作,而且get
方法可以继承set(target, propKey, value, receiver)
用于拦截target
对象上的propKey
的赋值操作,如果目标对象自身的某个属性不可写且不可配置,那set
方法将不起作用,第四个参数receiver
表示原始操作行为所在对象,一般是Proxy
实例本身,严格模式下,set
代理如果没有返回true
,就会报错apply(target, ctx, args)
用于拦截函数的调用,call
和reply
操作,而target
表示目标对象,ctx
表示目标对象上下文,args
表示目标对象的参数数组has(target, propKey)
用于拦截HasProperty
操作,即在判断target
对象是否存在propKey
属性时,会被这个方法拦截。此方法不判断一个属性是对象自身的属性,还是继承的属性,此方法不拦截for...in
循环construct(target, args)
此方法用于拦截new
指令,返回值必须为对象deleteProperty(target, propKey)
用于拦截delete
操作,如果这个方法抛出错误或者返回false
,propKey
属性就无法被delete
命令删除defineProperty(target, propKey, propDesc)
用于拦截Object.definePro
若目标对象不可扩展,增加目标对象上不存在的属性会报错;若属性不可写或不可配置,则不能改变这些属性getOwnPropertyDescriptor(target, propKey)
用于拦截Object.getOwnPropertyD()
返回值为属性描述对象或者undefined
getPrototypeOf(target)
主要用于拦截获取对象原型的操作,返回值必须是对象或者null
,否则报错。另外,如果目标对象不可扩展(non-extensible),getPrototypeOf
方法必须返回目标对象的原型对象,主要包括Object.prototype._proto_
Object.prototype.isPrototypeOf()
Object.getPrototypeOf()
Reflect.getPrototypeOf()
instanceof
isExtensible(target)
用于拦截Object.isExtensible
操作,该方法只能返回布尔值,否则返回值会被自动转为布尔值,它的返回值必须与目标对象的isExtensible属性保持一致,否则会抛出错误ownKeys(target)
用于拦截对象自身属性的读取操作,方法返回的数组成员,只能是字符串或 Symbol 值,否则会报错。若目标对象中含有不可配置的属性,则必须将这些属性在结果中返回,否则就会报错。若目标对象不可扩展,则必须全部返回且只能返回目标对象包含的所有属性,不能包含不存在的属性,否则也会报错。主要包括Object.getOwnPropertyNames()
Object.getOwnPropertySymbols()
Object.keys()
or...in
preventExtensions(target)
拦截Object.preventExtensions
操作。该方法必须返回一个布尔值,否则会自动转为布尔值setPrototypeOf()
主要用来拦截Object.setPrototypeOf
方法。返回值必须为布尔值,否则会被自动转为布尔值。若目标对象不可扩展,setPrototypeOf
方法不得改变目标对象的原型Proxy.revocable()
用于返回一个可取消的Proxy
实例
Reflect
es6 中将 Object
的一些明显属于语言内部的方法移植到了 Reflect
对象上(当前某些方法会同时存在于 Object
和 Reflect
对象上),未来的新方法会只部署在 Reflect
对象上。 Reflect
对象对某些方法的返回结果进行了修改,使其更合理。 Reflect
对象使用函数的方式实现了 Object
的命令式操作
静态方法
Reflect.get(target, name, receiver)
查找并返回target
对象的name
属性Reflect.set(target, name, value, receiver)
将target
的name
属性设置为value
。返回值为布尔值,true
表示修改成功,false
表示失败。当target
为不存在的对象时,会报错Reflect.has(obj, name)
是name in obj
指令的函数化,用于查找name
属性在obj
对象中是否存在。返回值为布尔值。如果obj
不是对象则会报错TypeError
Reflect.deleteProperty(obj, property)
是delete obj[property]
的函数化,用于删除obj
对象的property
属性,返回值为布尔值。如果obj
不是对象则会报错TypeError
Reflect.construct(obj, args)
等同于new target(...args)
Reflect.getPrototypeOf(obj)
用于读取obj
的_proto_
属性。在obj
不是对象时不会像Object
一样把obj
转为对象,而是会报错Reflect.setPrototypeOf(obj, newProto)
用于设置目标对象的prototype
Reflect.apply(func, thisArg, args)
等同于Function.prototype.apply.call(func, thisArg, args)
。func
表示目标函数,thisArg
表示目标函数绑定的this
对象,args
表示目标函数调用时传入的参数列表,可以是数组或类似数组的对象。若目标函数无法调用,会抛出TypeError
Reflect.defineProperty(target, propertyKey, attributes)
用于为目标对象定义属性。如果target
不是对象,会抛出错误。Reflect.getOwnPropertyDescriptor(target, propertyKey)
用于得到target
对象的propertyKey
属性的描述对象。在target
不是对象时,会抛出错误表示参数非法,不会将非对象转换为对象Reflect.isExtensible(target)
用于判断target
对象是否可扩展。返回值为布尔值。如果target
参数不是对象,会抛出错误Reflect.preventExtensions(target)
用于让target
对象变为不可扩展。如果target
参数不是对象,会抛出错误Reflect.ownKeys(target)
用于返回target
对象的所有属性,等同于Object.getOwnPropertyNames
与Object.getOwnPropertySymbols
之和