ES6一

ES6(ECMAScript 第六个版本)

ES6, 全称 ECMAScript 6.0 ,是 JavaScript 的下一个版本标准,2015.06 发版。
ES6 主要是为了解决 ES5 的先天不足,比如 JavaScript 里并没有类的概念,但是目前浏览器的 JavaScript 是 ES5 版本,大多数高版本的浏览器也支持 ES6,不过只实现了 ES6 的部分特性和功能。
ECMAScript 和JavaScript 什么关系?
ECMAScript 是一个语言的标准 if switch var 可以在JavaScript
解析JavaScript是浏览器的内核做的事情(5个内核)
JavaScript ECMAscript + WEBapi(DOM、BOM) = JavaScript
ActionScript + WEBapi(DOM、BOM)= flash(老版本)
ES6 新增了很多的语法规范,可以对写法和开发有很大的帮助,有很多新增的内容,以后慢慢的去适应es6的写法。有很多小的点,经常出现在面试中,对比性的学习思考以前的写法和现在的写法有什么不同的,有什么样的优化。
babel 编译 写完了es6的语法可以放在babel看看编译的结果
https://babeljs.io/repl
尽量的保证浏览器是最新的,如果实在有语法看不到效果的,再到编译器中看,node 全部都是ES6的语法.

ECMAScript 的历史

1996 ES1.0 Netscape公司叫js交个了ECMA的组织,es正式出现
1998 ES2.0
1999 ES3.0
2007 ES4.0 大的更新,大的改动。开发者完全的不认同。过于激进。被废除了
2008 ES3.1 严重缩水的4.0,名字Harmony ECMAHarmony
2009 ES5.0 正式发布,草案直接指向ES6.0
2013 ES6.0 草案指定完成
2013.12 ES6.0草案发布
2015.06 ES6.0正式发布 ES2015
2016 ES就不在使用版本号了,而是使用年份的代号了 ES7
2017 ES8
2018 ES9

变量声明const和let

let声明变量
1.let声明的变量不会挂在window中,不会造成全局变量的污染
2.新增了一个块级作用域{},以前只有函数作用域,全局作用域
3.let是不允许重复声明
4.let不会有声明提前(只是人为看到的效果,实际上是有声明提前,提前临时性的死区中:Cannot access ‘num’ before initialization) 面试点

console.log(a);  // undefined
var a = 'hello';

# 上面的代码相当于
var a;
console.log(a);
a = 'hello';

# 而 let 就不会被变量提升
console.log(a); // a is not defined
let a = 'hello';

# let 只能声明一次  var 可以声明多次:
let a = 1;
let a = 2;
var b = 3;
var b = 4;
a  // Identifier 'a' has already been declared
b  // 4

const声明常量
1.前四点跟let完全相同 增加几个点
5.不允许被修改(不允许改变内存空间的地址)
6.const声明和赋值必须一次性完成,并且后期不允许改变存储空间的地址

 const name = 'xx'
    name = 'aa' // 再次赋值此时会报错
//如果 const 的是一个对象,对象所包含的值是可以被修改的。
//抽象一点儿说,就是对象所指向的地址不能改变,而变量成员是可以修改的。
const student = { name: 'cc' }
    // 没毛病
    student.name = 'yy'
    // 如果这样子就会报错了
    student  = { name: 'yy' }
//const声明和赋值必须一次性完成
const abc;
  console.log(abc) //报错 

能使用const就使用const,不能使用就用let。常量的效率比变量要高

全局作用域和局部作用域(函数作用域),ES6新增了一个作用域 块级作用域,放置在{}

// 当成封闭空间使用,保护全局变量的安全
// (function(){
// })()
// ES6
// {
// }
let a = 10;
  {
   let a = 20;
   console.log(a);   //20
  }
  console.log(a);  //10
  //面试题
  let a = 10;
  {
   console.log(a);   //Cannot access 'a' before initialization
   let a = 20;   //a存到了临时性的死区中了
  }
  // let解决闭包的问题
  // 控制台有什么内容?,怎么改动可以输出0123456789?
  var arr = [];
  //第一个
  for(var i = 0;i<10;i++){
   arr[i] = function(){
    console.log(i);
   }
 }
 //第二个
 for(var i = 0;i<10;i++){
  (function(i){
    arr[i] = function(){
     console.log(i);
    }
   })(i)
  }
  //第三个
  for(let i = 0;i<10;i++){
   arr[i] = function(){
    console.log(i);
   }
 }
  arr[0]()
  arr[1]()
  arr[2]()
  arr[3]()
  arr[4]()
  arr[5]()
  arr[6]()
  arr[7]()
  arr[8]()
  arr[9]()
  console.log(i)
//上面第一个循环输出全部为10  
//第二个循环输出0到10 
//第三个输出0到9 最后外面的这个i会报错

模板字符串

模板字符串相当于加强版的字符串,用反引号 `,除了作为普通字符串,还可以用来定义多行字符串,还可以在字符串中加入变量和表达式。
字符串的换行

var str = "今天天气\n\
     很好";
  var str = [
   "今天天气",
   "很好"
  ]
  console.log(str.join("\n"))

ES6中提供字符串模板 ``

  let str = `今天天气
很好
sdkljf
sldkfj` 
  console.log(str)

模板字符串中的换行和空格都是会被保留的
字符串的拼接 + 变量 +

var day = "今天";
 var str = "天气不错";
console.log(day + str + "可以出去玩")

ES6中 `${表达式}字符串`

// 可以添加串
// 可以使用转义字符
// 可以嵌套
  var day = "今天";
  var str = "天气不错";
  console.log(`${day}${str}可以出去玩`)
  console.log(`${true?`今天`:`明天`}\n出去`)

解构赋值

结构化赋值
可以简化书写的长度,提升效率

//对象模型的解构
let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
// foo = 'aaa'
// bar = 'bbb'
let { baz : foo } = { baz : 'ddd' };
// foo = 'ddd'
//可嵌套可忽略
let obj = {p: ['hello', {y: 'world'}] };
let {p: [x, { y }] } = obj;
// x = 'hello'
// y = 'world'
let obj = {p: ['hello', {y: 'world'}] };
let {p: [x, {  }] } = obj;
// x = 'hello'
//不完全解构
let obj = {p: [{y: 'world'}] };
let {p: [{ y }, x ] } = obj;
// x = undefined
// y = 'world'
//解构默认值
let {a = 10, b = 5} = {a: 3};
// a = 3; b = 5;
let {a: aa = 10, b: bb = 5} = {a: 3};
// aa = 3; bb = 5;

//数组模型的解构
let arr = [1,2,3,4,10];
let [a,b,c,d] = arr; 
console.log(a,b,c,d) // 1234
let {length} = arr;
console.log(length) // 5
//可嵌套
let arr = [1,2,3,{name:'jack'}];
// a : 1 b : 2 c : 3 name:jack
let {0:a,1:b,2:c,3:{name:oName}} = arr;
console.log(a,b,c,oName) //1 2 3 "jack"
//可忽略
let [,,,{name : oName}] = arr;
console.log(oName) //jack
//不完全解构
let [a = 1, b] = []; // a = 1, b = undefined
//解构默认值
let [a = 2] = [undefined]; // a = 2

…运算符

写 收集
运用在数组中,函数中 object是ES7新增的

// ...运算符
  function sum(a,b,...arg){  //收集参数只能放在最后一个参数
   // arg.push(6)
   console.log(a,b,arg) 1 2 [3, 4, 5]
  }
  sum(1,2,3,4,5)
// ES6(数组),ES7(object)
  let arr = [1,2,3];
  console.log(...arr); //123
  let arr2 = [4,5,6];
  let newArr = [...arr,...arr2];
  console.log(newArr) //123456
// 克隆  浅克隆
  let arr1 = [1,2,3,4,{name:"jack"}];
  let arr2 = [...arr1];
  console.log(arr1,arr2);  
  console.log(arr1 == arr2);  //false
  console.log(arr1[4] == arr2[4]); //true   
// 在es7中的运用   针对于对象的运用
let company = {
   name : "bailiban",
   age : 16
  };
  let leader = {
   name : "peng",
   age : 18
  }
  let teachDepartment = {
   leader : {
    ...leader
   },
   personNum : 20,
   data : [new Date()]
  };
  let obj = {
   ...company,
   ...teachDepartment
  }
  console.log(obj);
  obj.leader.name = "yin";
  console.log(obj)
  console.log(leader)
// 深克隆   会存在问题   对引用值直接转化,不推荐使用
  let obj2 = JSON.parse(JSON.stringify(teachDepartment));
  obj2.leader.name = "yin";
  console.log(teachDepartment)
  console.log(obj2)
// jquery  
// $.extend() 抄袭
// assign({},,,,,,)   浅克隆
// let obj = Object.assign({"asdf":"asdfsdf"},company,teachDepartment);
// console.log(obj)    

函数

参数默认值 可以传递表达式,不能传递语句
arguments 严格模式中,arguments和函数的形参不存在关系,没有对应的映射关系
注意: 只要给函数加上了参数默认值,该函数就自动变成严格模式
形参和let,const一样,有自己的作用域,根据声明的顺序,会产生临时性死区

// ES5 给函数定义参数默认值
function foo(num) {
  num = num || 200;
  return num;
}
// ES6 提供新内容,参数可以加默认值
  function fun(a,b=10,c=20){
   return a+b+c;
  }
// 只有在未传递参数,或者参数为 undefined 时,才会使用默认参数,null 值被认为是有效的值传递。
console.log( fun(undefined,undefined,30) ); //NaN
console.log( fun(30) ) //60
console.log( fun(10,undefined,30) ) //50 
console.log( fun(10,null,30) )// 40  //null在数学中,默认的为0,不要传递null  
//函数参数默认值存在暂时性死区,在函数参数默认值表达式中,还未初始化赋值的参数值无法作为其他参数的默认值。
function test(a=b,b){   //Cannot access 'b' before initialization
   console.log(a,b)
  }
  test(undefined,2)

…运算符 起到参数收集作用
1.收集符只能出现一次
2.一个函数,剩余参数收集只能在最后一个形参

function sum(a,b,c,...args){
   console.log(args) //[4, 5, 6]
   var n = 0
   for(var i = 0;i < arguments.length;i ++){
    n += arguments[i]
   }
   return n;
  }
  console.log(sum(1,2,3,4,5,6)) 
  //在语义上,无法从函数本身来确定函数的用途

函数的真正用途
普通函数 纯小写
构造函数 大驼峰命名 首字母大写
新增 new.target 构造函数必须使用new来进行调用

function Person(firstName,lastName){
   // 加判断   ES6以前是没有办法完美解决
   // if(!(this instanceof Person)){
   //  throw new Error("该函数必须使用new调用")
   // }
   // 如果没有使用new 关键字调用函数,则返回undefined
   // 如果使用了new调用,则返回的是函数的本身
   if(new.target === undefined){
    throw new Error("该函数必须使用new调用")
   }
   this.firstName = firstName;
   this.lastName = lastName;
   this.fullName = `${firstName} ${lastName}`
  }
  const p1 = new Person("张","三");
  console.log(p1);
  const p2 = Person("张","三");
  console.log(p2)
  const p3 = Person.call(p1,"张","三")
  console.log(p3) // instanceof 检测不出来

箭头函数
语法: 箭头函数是一个函数表达式,理论上,任何使用函数表达式的地方都可以改成箭头函数

(参数1,参数2...) => {
  函数体
 }
简写
1.如果参数只有一个,可以省略小括号
参数 => {}
2.如果箭头函数只有一条返回语句,可以省略花括号,可以省略return
参数 => 返回值
3.如果返回值是一个对象的时候,就会认为成函数体,把返回值变成表达式的形式,为了区分于代码块,要用 () 将对象包裹起来。
const obj = (a,b) => 
   ({
    a : a,
    b : b
   })
   console.log( obj(1,2) )

注意
1.箭头函数中没有this,argument,new.target,如果要强行使用,则指向函数外层对应的this,argument,new.target
this指向问题

  • 1.对象调用函数,this指向对象
  • 2.直接调用函数,this指向window
  • 3.如果使用了new关键字,this指向新创建的对象
  • 4.如果使用apply,call,bind this指向绑定的数据
  • 5.如果是DOM事件函数,this指向事件源

2.箭头函数没有原型,所有说占用空间非常小,不能当成构造函数来使用
适合使用的场景

  1. 临时使用的函数,并不会刻意的去调用
    异步的处理函数
    事件的处理
  2. 继续去沿用外层的this
  3. 对象的属性不要去用箭头函数,除非是特别的需求
  4. 组方法的时候,保证代码的简洁
// 回调函数
var Person = {
    'age': 18,
    'sayHello': function () {
      setTimeout(function () {
        console.log(this.age);
      });
    }
};
var age = 20;
Person.sayHello();  // 20

var Person1 = {
    'age': 18,
    'sayHello': function () {
      setTimeout(()=>{
        console.log(this.age);
      });
    }
};
var age = 20;
Person1.sayHello();  // 18
//当我们需要维护一个 this 上下文的时候,就可以使用箭头函数。

不适合使用的场景
定义函数的方法,且该方法中包含 this

var Person = {
    'age': 18,
    'sayHello': ()=>{
        console.log(this.age);
      }
};
var age = 20;
Person.sayHello();  // 20
// 此时 this 指向的是全局对象
 
var Person1 = {
    'age': 18,
    'sayHello': function () {
        console.log(this.age);
    }
};
var age = 20;
Person1.sayHello();   // 18
// 此时的 this 指向 Person1 对象

//需要动态 this 的时候
var button = document.getElementById('userClick');
button.addEventListener('click', () => {
     this.classList.toggle('on');
});
//button 的监听函数是箭头函数,所以监听函数里面的 this 指向的是定义的时候外层的 this 对象,即 Window,导致无法操作到被点击的按钮对象。

对象

1.对象初始化简写

// ES5
function people(name, age) {
  return {
    name: name,
    age: age
  };
}
// ES6
function people(name, age) {
  return {
    name,
    age
  };
}

2.对象字面量简写(省略冒号与 function 关键字)

// ES5
var people1 = {
  name: 'bai',
  getName: function () {
    console.log(this.name);
  }
};
// ES6
let people2 = {
  name: 'bai',
  getName () {
    console.log(this.name);
  }
};

3.计算属性名

  const prop1 = "name";   //我们知道属性名是什么,由后台返回给你的
  const prop2 = "age";
  const prop3 = "say"
  const user = {
   [prop1] : "尹老师",
   [prop2] : 30,
   [prop3](){
    console.log(this[prop1],this[prop2])
   }
  }
  console.log(user[prop1])
  user[prop3]()

新增了API
1.Object.is(value1, value2)
用来比较两个值是否严格相等,与(===)基本类似。

Object.is("q","q");      // true
Object.is(1,1);          // true
Object.is([1],[1]);      // false
Object.is({q:1},{q:1});  // false

与(===)的区别

//一是+0不等于-0
Object.is(+0,-0);  //false
+0 === -0  //true
//二是NaN等于本身
Object.is(NaN,NaN); //true
NaN === NaN  //false

2.assign() 用于混合对象,带浅克隆 …ES7

const obj1 = {
   a : 123,
   b : 456,
   c : "abc"
  }
  const obj2 = {
   a : 789,
   e : "asdf"
  }
  // 将2的内容覆盖到1  会对1产生影响
  const obj = Object.assign({},obj1,obj2)
  console.log(obj)
  console.log(obj == obj1)

3.getOwnPropertyNames() 枚举的顺序,返回一个数组,枚举出来对象的属性
对象的顺序其实是浏览器厂商自行规定
先排数字,升序
再排其他,按照书写顺序

const obj = {
   e : 1,
   a : 2,
   c : 3,
   0 : 6,
   5 : 7,
   2 : 3
  }
  console.log(obj) //{0: 6, 2: 3, 5: 7, e: 1, a: 2, c: 3}
  const arr = Object.getOwnPropertyNames(obj);
  console.log(arr);   //["0", "2", "5", "e", "a", "c"]

4.setPrototypeOf() 设置某个对象的隐式原型 proto

const obj1 = {
   a : 1
  }
  const obj2 = {
   b : 2
  }
  // obj1.__proto__ = obj2   必须要通过构造函数来完成
  Object.setPrototypeOf(obj1,obj2)
  console.log(obj1) //{a: 1} 
  console.log(obj1.__proto__)   //{b: 2}

面向对象 一种编程思想,跟语言没有关系

面向过程

// 三步
  // 1.打开冰箱
  function openFrige(){
  }
  // 2.大象放进去
  function elephantIn(){
  }
  // 3.关上冰箱
  function closeFrige(){
  }

面向对象 大型的项目,大型的模块

// 不去思考过程,而是去思考有几个对象 大象 冰箱
 function Elephant(){}
 function Frige(){}
 Frige.prototype.openDoor = function(){}
 Frige.prototype.closeDoor = function(){}
 Frige.prototype.join = function(){}
 var frig = new Frige();
 frig.openDoor()
 var ele = new Elephant()
 frig.join(ele)
 frig.closeFrige()
// 如果功能非常小,完全,没有必要按照面向对象的思维去思考
发布了24 篇原创文章 · 获赞 0 · 访问量 744

猜你喜欢

转载自blog.csdn.net/weixin_45846263/article/details/104986623