ES6
一、ECMAScript规范
- ECMAScript是一个标准,JavaScript是一个标准的实现。js是跑在浏览器端,浏览器对一些语言特性的实现,有一些滞后,所以对于用户侧的升级,也有一些滞后。所以就要对js做一些降级,就要用到Babel,Babel就是浏览器的版本,和语言本身有差异,所以对语言,进行编译降级。
- Babel7根据用户的浏览器的特性,在运行时动态的引入一些
polyfill
;bundle size最小
babel官网:www.babeljs.cn/
二、变量-let&const
以前的var声明变量存在的问题:
- 可以重复声明,且没有报错
- 无法限制修改,没有常量的概念
- 没有块级作用域,var的作用域是函数 所以有了两种新的变量声明方法 let 和 const:
- let 和 const 不能重复声明,重复声明会报错
- let 声明变量,有其独立的块级作用域,可以重新赋值,不可以变量提升
- const 声明常量,不可以重复赋值 以前早期js中一个经典的案例:
<body>
<input type="button" value="按钮1" />
<input type="button" value="按钮2" />
<input type="button" value="按钮3" />
</body>
<script>
var aBtn = document.getElementsByTagName('input')
for(var i = 0;i<aBtn.length;i++){
aBtn[i].onclick = function(){
alert(i)
}
}
//结果: 3,3,3
</script>
以前的解决办法:在alert外面加了一个层数包裹了一下,传入的时候i不会改变
for(var i = 0;i<aBtn.length;i++){
(function(i){
aBtn[i].onclick = function(){
alert(i)
}
})(i)
}
现在使用ES6可以直接只用let,因为他有自己的块级作用域
三、箭头函数
() => {}
- 如果只有一个return的时候 ,{}可以省略
- -箭头函数不能试用的一些地方?
- arguments
- yield
- 构造函数的原型方法上:Person.prototype.xxx,因为的this的指向的问题
- 与this相关的一些东西都不能用
发散:new 一个箭头函数?
const TestArrowFunc = () => {
this.age = "18"
this.name = "wenqing"
}
const t = new TestArrowFunc()
// -报错 TestArrowFunc is not a constructor
-但在babel编译时,会把*this*转为(void 0)
四、函数的参数
- 收集参数
function show(a,b,...args){
console.log(a)
console.log(b)
console.log(args)
}
show(5,12,20,25,30,35,40)
- 展开数组
const _arr = [1,2,3]
show(..._arr) === show(1,2,3)
* ..._arr 相当于把1,2,3摆在这里*
- 默认参数
function fn(a,b,c = 5) {
console.log(a,b,c)
}
fn(2,12)
fn(2,12,25)
//打印结果:2 12 5
2 12 25
五、结构赋值
- 左右两边结构必须一样
- 右边必须合法
- 声明和赋值必须在一起
let [a,b,c] = [1,2,3]
console.log(a,b,c)
let {d,e} = {{“text”:“123”},[2,5,8]}
console.log(d,e)
六、字符串
1.两个新方法 : startsWith endsWith
2.字符串模板
let name = '晚晚'
let str = `你好呀${name}`
console.log(str)
打印结果:你好呀晚晚
七、面向对象
1.基本使用
以前没有class 出来之前,js的面向对象写法:
//构造函数
function User(name,pass) {
this.name = name
this.pass = pass
}
//给原型加方法
User.prototype.showName = function(){
console.log(this.name)
}
User.prototype.showPass = function(){
console.log(this.pass)
}
let _user = new User('WANWAN','123456')
_user.showName()
_user.showPass()
ES6中的class使用如下:
class User {
//构造器
constructor(name,pass) {
this.name = name
this.pass = pass
}
showName(){
console.log(this.name)
}
showPass(){
console.log(this.pass)
}
}
let _user = new User('WANWAN','123456')
_user.showName()
_user.showPass()
2.继承
但是面向对象最重要的功能是 继承 ,以前js中写法:
function User(name,pass) {
this.name = name
this.pass = pass
}
User.prototype.showName = function(){
console.log(this.name)
}
User.prototype.showPass = function(){
console.log(this.pass)
}
function VipUser(name,pass,level){
//继承原来的属性
User.call(this,name,pass)
this.level = level
}
//新对象的原型指向父类的构造函数
VipUser.prototype = new User()
//构造函数重新指向
VipUser.prototype.constructor = VipUser
VipUser.prototype.showLevel = function(){
console.log(this.level)
}
let _user = new VipUser('WANWAN','123456',12)
_user.showName()
_user.showPass()
_user.showLevel()
现在使用extend关键字就会变得很简单
class User {
constructor(name,pass) {
this.name = name
this.pass = pass
}
showName(){
console.log(this.name)
}
showPass(){
console.log(this.pass)
}
}
class VipUser extends User{
constructor(name,pass,level) {
super(name,pass);
this.level = level
}
showLevel(){
console.log(this.level)
}
}
let _user = new VipUser('WANWAN','123456',12)
_user.showName()
_user.showPass()
_user.showLevel()
3.get & set
class User {
constructor(name,pass) {
this.name = name
this.pass = pass
}
_age = ""
get age(){
return 17
}
set age(val){
this._age = val
}
}
const _u = new User('wanwan',123)
_u.age = 22
console.log(_u.age)
八、Promise
九、Object.assign
到底是深拷贝还是浅拷贝?首先,看下基本使用
let foo = {foo:"foo"}
let bar = {bar:"bar"}
let baz = {baz:"baz"}
const obj = Object.assign(foo,bar,baz)
console.log(obj)
打印结果:
{ foo: 'foo', bar: 'bar', baz: 'baz' }
这没什么问题,如果给bar传入一个新值呢?
const obj = Object.assign(foo,bar,baz)
bar.bar = 'bar2'
console.log(bar)
console.log(obj)
打印结果:
{ bar: 'bar2' }
{ foo: 'foo', bar: 'bar', baz: 'baz' }
看起来也没什么问题,但是如果bar是引用类型呢?
let foo = {foo:"foo"}
let bar = {bar:{
bar:"bar"
}}
let baz = {baz:"baz"}
const obj = Object.assign(foo,bar,baz)
bar.bar.bar = 'bar2'
console.log(bar)
console.log(obj)
打印结果:
结论: 按照第一层解构之后,第二层复制的就是引用,也就是说第一层是深拷贝,第二层是浅拷贝
如果在这里打印:
console.log(obj === foo)
其结果为true
十、Generator
十一、Proxy
使用vue的同学应该比较清楚,vue2使用的Object.defineproperty并不是真正的代理。vue3中使用的proxy也是它的特色之一,且效率更高。
Proxy 可以对目标对象的读取、函数调用等操作进行拦截,然后进行操作处理。