学习笔记:ES6

130 阅读4分钟

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

见其他笔记[juejin.cn/post/708860…]

九、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)

打印结果:

1651045121(1).png

结论: 按照第一层解构之后,第二层复制的就是引用,也就是说第一层是深拷贝,第二层是浅拷贝

如果在这里打印:
console.log(obj === foo)
其结果为true

十、Generator

见其他笔记[juejin.cn/post/709153…]

十一、Proxy

使用vue的同学应该比较清楚,vue2使用的Object.defineproperty并不是真正的代理。vue3中使用的proxy也是它的特色之一,且效率更高。
Proxy 可以对目标对象的读取、函数调用等操作进行拦截,然后进行操作处理。