ES5-ES6的部分新特性

ES5-ES6新特性介绍

ES5新特性

严格模式

  • 除了正常运行模式(混杂模式),ES5添加了第二种运行模式:”严格模式”(strict mode)。顾名思义,这种模式使得Javascript在更严格的语法条件下运行
  • 目的:
    • 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
    • 消除代码运行的一些不安全之处,为代码的安全运行保驾护航;
    • 为未来新版本的Javascript做好铺垫;
  • 使用
    • 在全局或函数的第一条语句定义为: ‘use strict’;
    • 如果浏览器不支持, 只解析为一条简单的语句, 没有任何副作用;
  • 语法和行为改变

    • 必须用var声明变量;

      <script type="text/javascript">
        "use strict"
        age = 12;
        console.log(age);// age is not defined
      </script>
    • 禁止自定义的函数中的this指向window;

      • 因此使用构造函数时,如果忘了加new,this不再指向全局对象,而是报错。
        "use strict"
        function Person(name,age) {
        //在严格模式下,自定义普通函数中的this是禁止指向window的。
          console.log(this);
          //undefined
            this.name = name;
            this.age = age;
        }
        Person('kobe',12);
        
        //定时器不是自定义函数,所以可以输出window
        setTimeout(function () {
          console.log(this);//window
        }, 1000);
    • 创建eval作用域;

    • eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码。
    • 正常模式下,Javascript语言有两种变量作用域(scope):全局作用域和函数作用域。严格模式创设了第三种作用域:eval作用域。
    • 正常模式下,eval语句的作用域,取决于它处于全局作用域,还是处于函数作用域。严格模式下,eval语句本身就是一个作用域,不再能够生成全局变量了,它所生成的变量只能用于eval内部。

      var name = 'kobe';
      eval('var name = "anverson";console.log(name)');//anverson
      console.log(name);//kobe
    • 对象不能有重名的属性;正常模式下最后赋值的属性会覆盖前面的值,严格模式下属于语法错误;

JSON的对象

  • JSON基于两种结构:
    • “名称/值”对的集合;
    • 值的有序列表;
  • JSON具有以下这些形式:

    • 对象(object):是一个无序的“‘名称/值’对”集合。

      • 一个对象以“{”(左括号)开始,“}”(右括号)结束。
      • 每个“名称”后跟一个“:”(冒号);“‘名称/值’ 对”之间使用“,”(逗号)分隔。
        {'名值对1''名值对2'......}
    • 数组(array):是值(value)的有序集合。

      • 一个数组以“[”(左中括号)开始,“]”(右中括号)结束。
      • 值之间使用“,”(逗号)分隔。
        [value1,value2......]
    • 值(value):可以是双引号括起来的字符串(string)、数值(number)、true、false、 null、对象(object)或者数组(array)。这些结构可以嵌套。

    • 字符串(string):是由双引号包围的任意数量Unicode字符的集合,使用反斜线转义。
    • JSON 字符串:数值(number) 也与C或者Java的数值非常相似。只是JSON的数值没有使用八进制与十六进制格式。
  • JSON的两种方法

    • JSON.stringify(obj/arr); js对象(数组)转换为json对象(数组)
    • JSON.parse(json); json对象(数组)转换为js对象(数组)
      var obj = {name:"kobe",age:39};
      
      // JSON.stringify(obj/arr); js对象(数组)转换为json对象(数组)
      obj = JSON.stringify(obj);
      console.log(obj);//{"name":"kobe","age":39}
      console.log(typeof obj);
      
      //JSON.parse(json); json对象(数组)转换为js对象(数组)
      obj = JSON.parse(obj);//string
      console.log(obj);//{name: "kobe", age: 39}
      console.log(typeof obj);//object

Object扩展

  • Object扩展了好一些静态方法, 常用的2个:

    • Object.create(prototype, [descriptors])

      • 作用:
        • 以指定对象为原型创建新的对象;
        • 为新的对象指定新的属性, 并对属性进行描述;
      • 有关参数:
        • value : 指定值
        • writable : 标识当前属性值是否是可修改的, 默认为true
        • get : 用来得到当前属性值的回调函数
        • set : 用来监视当前属性值变化的回调函数
          var obj = {name:'ldy',age:18};
          var obj1 = Object.create(obj);
          console.log(obj1);
          //直接继承obj的属性,作为自己的原型对象
            /*
            * {};
            * __proto__: age: 18name: "ldy"__proto__: Object
            */
          obj1.sex = '男';
          //继承obj的对象obj1可以添加直接属性
          console.log(obj1);
            /*
            * {sex: "男"};
            * __proto__: age: 18name: "ldy"__proto__: Object
             */
          
          //可以直接继承obj属性作为原型链上的属性,并且直接通过第二个参数传入一个对象,作为对象的直接属性。
          //注意:第二个参数内的键值对的值需要是一个对象{value:...}。
          obj1 = Object.create(obj,{
              address:{value:'daguanyuan'},
              att:{value:'wenrou'}
          });
          console.log(obj1);
            /*
            * {address: "daguanyuan", att: "wenrou"}
            * __proto__:
           *  age:18
           *  name:"ldy"
            * */
    • Object.defineProperties(object, descriptors)

      • 作用: 为指定对象定义扩展多个属性
      • 存取器属性:setter,getter一个用来存值,一个用来取值
      • 对象本身的两个方法
        • get propertyName(){} 用来得到当前属性值的回调函数;
        • set propertyName(){} 用来监视当前属性值变化的回调函数;
      • 注意,get方法只有在调用它掌控的属性的时候,才会被调用该get方法的。
     var obj2 = {wname:'xiannv1',wname2:'xiannv2'};
     Object.defineProperty(obj2, 'wife2',{value:'ldy'});
     Object.defineProperties(obj2,{
         wife3:{
             value:'xbc'
         },wife4:{
             get:function(){
             //此时会将return后的内容作为值返回给obj2.wife4;
                 return this.wifevalue;
             },
             set:function(data){
             //set方法里接收的就是设置的obj2.wife4 = 'jyc'的值。
                 console.log(data);//'jyc'
                 this.wifevalue = data;
             }
         }
     })
     obj2.wife4 = 'jyc';
     console.log(obj2.wife4);//'jyc'
     console.log(obj2);//{wname: "xiannv1", wname2: "xiannv2", wifevalue: "jyc", wife2: "ldy", wife3: "xbc", wife4:"jyc"}

Array扩展

  • Array.prototype.indexOf(value) : 得到值在数组中的第一个下标
  • Array.prototype.lastIndexOf(value) : 得到值在数组中的最后一个下标
  • Array.prototype.forEach(function(item, index){}) : 遍历数组
  • Array.prototype.map(function(item, index){}) : 遍历数组返回一个新的数组,返回加工之后的值
  • Array.prototype.filter(function(item, index){}) : 遍历过滤出一个新的子数组, 返回条件为true的值
//map\forEach\filter区别
var arr = [23,65,6,43,1,5,3,2,8];
//filter相当于筛选,返回的是满足条件的筛选值
var arr3 = arr.filter(function (item) {
    return item<20;
})
console.log(arr3);// [6, 1, 5, 3, 2, 8]

//foeEach相当于是遍历,是将原数组都输出;但是并不能直接对遍历的值进行加工
var arr2 = arr.forEach(function (item) {
    console.log(arr);//[23, 65, 6, 43, 1, 5, 3, 2, 8]
    return item*3;
})
console.log(arr2);//undefined

//map可以对遍历出来的字,进行加工,返回的是一个加工后的新数组。
var arr1 = arr.map(function (item) {
    return item*3;
})
console.log(arr);//[23, 65, 6, 43, 1, 5, 3, 2, 8]
console.log(arr1);//[69, 195, 18, 129, 3, 15, 9, 6, 24]

function扩展

  • Function.prototype.bind(obj) :
    • 作用: 将函数内的this绑定为obj, 并将函数返回
  • 面试题: 区别bind()与call()和apply()?

    • 都能指定函数中的this;
    • call()/apply()是立即调用函数;
    • bind()是将函数返回;
    var age = 20;
    var obj = {username:'kobe',age:28};
    function fn(username) {
        console.log(this.age,username);
    };
    //apply和call都是一调用就立即执行
    //apply只传入数组,而call可以传非数组
    fn.apply(obj);//直接执行了,输出了28he undifined;
    fn.apply(obj,['xbc']);//28 "xbc"
    fn.call(obj,'jyc');//28 "jyc"
    //bind调用之后没有立即执行函数,在想执行的时候再调用。传入的参数和call一样。
    fn.bind(obj,'jby');//无
    fn.bind(obj,'jby')();//28 "jby"

ES6新特性

新关键字

let关键字
  • 1.作用:
    • 与var类似, 用于声明一个变量
  • 2.特点:
    • 在块作用域内有效
    • 不能重复声明
    • 不会预处理, 不存在提升
  • 3.应用:
    • 循环遍历加监听
    • 使用let取代var是趋势
let btn = document.getElementsByTagName('button');
//方法一
  for(var i=0;i<btn.length;i++){
      (function (i) {
          btn[i].onclick = function () {
              alert(i);
          }
      })(i)
  }
//方法二
  for(var i=0;i<btn.length;i++){
      btn[i].dream = i;
      btn[i].onclick = function () {
              alert(this.dream);
          }
  }
//方法三
  for(let i=0;i<btn.length;i++){
      btn[i].onclick = function () {
          alert(i);
      }
  };
const定义一个常量
  • 1.作用:
    • 定义一个常量
  • 2.特点:
    • 不能修改
    • 其它特点同let
  • 3.应用:
    • 保存不用改变的数据
const sex = 'nan';
  console.log(sex);
  sex = '女';//Assignment to constant variable.
  console.log(sex);

变量的结构赋值

  • 1.理解:
    • 从对象或数组中提取数据, 并赋值给变量(多个)
  • 2.对象的解构赋值: let {n, a} = {n:’tom’, a:12}
let obj = {name:'ldy',age:'17'};
let {age,name} = obj;
console.log(age,name);//17 ldy
  • 3.数组的解构赋值: let [a,b] = [1, ‘atguigu’];
let arr = ['a','b','c','d'];
let [a,b,c,d] = arr;
console.log(a);//'a'
console.log(b);//'b'
console.log(c);//'c'
console.log(d);//'d'
  • 4.用途
    • 给多个形参赋值
//当传入的对象有很多属性,但是需要传入的实参仅需要其中的两个,那么就可以通过对象的解构赋值,接收传入实参对象中的其中某两个属性。
function fn({name,age}) {
  console.log(name,age);//hlm 38
}
let obj1 = {add:'dgy',name:'hlm',sex:'nan',age:38};
fn(obj1);

模版字符串

  • 模板字符串 : 简化字符串的拼接
    • 模板字符串必须用 “ 包含
    • 变化的部分使用${xxx}定义
let obj = {
    name : 'anverson',
    age : 41
};
console.log('我叫:' + obj.name + ', 我的年龄是:' + obj.age);
//我叫:anverson, 我的年龄是:41
console.log(`我叫:${obj.name}, 我的年龄是:${obj.age}`);//我叫:anverson, 我的年龄是:41

简化对象写法

  • 省略同名的属性值
  • 省略方法的function
let x = 3;
let y = 5;
  //普通写法
//  let obj = {
//      x:x,
//      y:y,
//      getPoint:function () {
//          return 'fun';
//      }
//  }
//  console.log(obj);//{x: 3, y: 5, getPoint: ƒ}

//简化写法
let obj = {
    x:x,
    y:y,
    getPoint() {
        return 'fun';
    }
}
console.log(obj);//{x: 3, y: 5, getPoint: ƒ}

三点运算符

  • 用途

    • 1.rest(可变)参数:用来取代arguments 但比 arguments 灵活,只能是最后部分形参参数
    //简单举例
    function fun(...values) {
            console.log(arguments);// [1, 2, 3, callee: (...), Symbol(Symbol.iterator): ƒ];一个对象,类数组
    //        arguments.forEach(function (item, index) {
    //            console.log(item, index);//报错
    //        });
            console.log(values);//[1, 2, 3];一个数组
            values.forEach(function (item, index) {
                console.log(item, index);
            })
        }
        fun(1,2,3);
    
    //详解
    let fun1=function(...args){
    for(let arg of args){
        console.log(arg);
    };
    console.log(args)
    };
    fun1('a','b','c');//a b c,[a,b,c]
    fun1(1,2);//1 2,[1,2] ...args表示了所有的形参,不管传入多少参数,都可以通过args进行遍历得到,args则集合所有的参数组成参数数组
    
    
    let fun2=function(arr,...args){
    console.log(arr);
    console.log(args);
    };
    fun2(1,2,3);//1, [2,3]
    fun2(1);//1, []当...args有其他参数时,rest参数args数组集合除去前面参数之后的参数。
    
    
    let fun3=function(arr1,..args,arr2){
    console.log(args);
    }//此时报错!!!切记,三点作为rest参数的时候,其后不能再有任何参数,只能作为最后一个角色出现!
    • 2.扩展运算符
    let arr1 = [1,3,5];
    let arr2 = [2,...arr1,6];
    arr2.push(...arr1);
    
    //详细讲解
    let arr=[1,2,3];
    console.log(...arr);//1, 2, 3返回数组中的各项
    
    let a=[2,3];
    console.log(1,...a,4);//1,2,3,4扩展运算符可以放在中间
    
    let divs=document.querySelectorAll('div');
    [...divs];//Array[300],[]可以将divs转为数组解构;
    console.log(...divs);//div1,div2....遍历divs各项
    
    let set=new Set([1,2,3,3]);
    [...set];//返回数组[1,2,3],可以将set数据结构转化为数组
    
    let map=new Map([[1,'a'],[2,'b'],[3,'c']]);
    [...map.keys];//返回[1,2,3],属性数组;
    [...map.values];//返回[a,b,c],value数组
    
    ///////////////
    [...'wbiokr'];//["w", "b", "i", "o", "k", "r"]遍历字符串,返回各个字符;
    
    let str='abc';
    ['aaa',...str,'ccc'];//[aaa, a, b, c, ccc]扩展运算符位置比较任性

形参的默认值

  • 形参的默认值—-当不传入参数的时候默认使用形参里的默认值

     //定义一个点的坐标
        function Point(x=12, y=12) {
            this.x = x;
            this.y = y;
        }
        let point = new Point(25, 36);
        console.log(point);//Point {x: 25, y: 36}
        let p = new Point();
        console.log(p);//Point {x: 12, y: 12}

class类

  • 1.通过class定义类/实现类的继承
  • 2.在类中通过constructor定义构造方法
  • 3.通过new来创建类的实例
  • 4.通过extends来实现类的继承
  • 5.通过super调用父类的构造方法
  • 6.重写从父类中继承的一般方法
//  class定义类的方式,构造对象
  class Mul{
//      类里面的属性,其实可以理解为实例对象的构造函数。
//      所以它里面定义的属性和方法,在实例对象的直接属性之中。
      constructor(name,age){
          this.name = name;
          this.age = age;
//          this.hello = function () {
//              console.log(5678);
//          }
      }
//      这个定义的方法,可以理解为定义在构造函数的原型上面,所以只能在实例对象的__proto__上可以找到。
      showName(){
          console.log('name');
      }
  }
  let mul = new Mul('zly',14);
  console.log(mul);//Mul {name: "zly", age: 14}

  //实现类的继承
  class newFun extends Mul{
      constructor(name,age,sex){
          super(name,age);//调用父类的构造方法
          this.sex = sex;
          this.newMsg = function () {
              console.log(this.age,this.sex,this.name);
          }
      }
//      showName(){
//          console.log('name');
//      }
  }
  let newfun = new newFun('SWK',23,'nan');
  console.log(newfun);//newFun {name: "SWK", age: 23, sex: "nan", newMsg: ƒ}
//  此时的newfun的原型对象的原型对象中有showName(){console.log('name');}函数。因为newfun是继承Mul类的,而super方法是继承Mul类的构造方法作为了自己的直接属性,可是showName()是定义在Mul的原型上的,并没有继承到直接属性上,所以就在newfun的原型的原型上,extends方法是类的继承,。

字符串扩展

  • 1.includes(str) : 判断是否包含指定的字符串
var str = 'asdkjhgfdfghjkl';
console.log(str.includes('w'));//false
console.log(str.includes('j'));//true
  • 2.startsWith(str) : 判断是否以指定字符串开头
var str = 'asdkjhgfdfghjkl';
console.log(str.startsWith('a'));//true
console.log(str.startsWith('as'));//true
console.log(str.startsWith('b'));//false
  • 3.endsWith(str) : 判断是否以指定字符串结尾
var str = 'asdkjhgfdfghjkl';
console.log(str.endsWith('l'));//true
console.log(str.endsWith('kl'));//true
console.log(str.endsWith('k'));//false
  • 4.repeat(count) : 重复指定次数
var str = 'asdkjhgfdfghjkl';
console.log(str.repeat(2));//asdkjhgfdfghjklasdkjhgfdfghjkl

数值扩展

  • 1.二进制与八进制数值表示法: 二进制用0b, 八进制用0o;
console.log(0b1010);//10
console.log(0o65);//53
  • 2.Number.isFinite(i) : 判断是否是有限大的数
console.log(Number.isFinite(NaN));//false
console.log(Number.isFinite(10));//true
  • 3.Number.isNaN(i) : 判断是否是NaN
console.log(Number.isNaN(NaN));//true
console.log(Number.isNaN(true));//false
  • 4.Number.isInteger(i) : 判断是否是整数
  • 5.Number.parseInt(str) : 将字符串转换为对应的数值
  • 6.Math.trunc(i) : 直接去除小数部分
console.log(Math.trunc(120.4));//120
console.log(Math.trunc(0.120));//0

数组扩展

  • 1.Array.from(v) : 将伪数组对象或可遍历对象转换为真数组
//html结构上有三个button按钮;
//通过dom获得一个类数组;
var btn = document.getElementsByTagName('button');
console.log(btn);//HTMLCollection(3);一个html对象,是一个类数组
//通过from方法,将类数组转化为真数组;
var btn1 = Array.from(btn);
console.log(btn1);//Array(3); [button, button, button]
  • 2.Array.of(v1, v2, v3) : 将一系列值转换成数组
var btn = document.getElementsByTagName('button');
console.log(btn);//HTMLCollection(3);一个html对象,是一个类数组
var btn2 = Array.of(btn);
console.log(btn2);//[HTMLCollection(3)];这是一个数组,这个数组只有一项.

var arr = 'sdf[sdf]';
console.log(Array.of(arr));//["sdf[sdf]"]
var str = 'a,b,c,d,e';
console.log(Array.of(str));//["a,b,c,d,e"]
  • 3.find(function(value, index, arr){return true}) : 找出第一个满足条件返回true的元素
var arr = [2,3,4,'f','s','e','r'];
console.log(arr.find(function (item) {
    return item<5;
}));//2;找到的是第一个小于5的元素,直接返回。
  • 4.findIndex(function(value, index, arr){return true}) : 找出第一个满足条件返回true的元素下标
var arr = [2,3,4,'f','s','e','r'];
console.log(arr.findIndex(function (item) {
    return item<5;
}));//0;找到的是第一个小于5的元素,正好是2,返回他的下标

Object扩展

  • 1.Object.is(v1, v2)

    • 判断2个数据是否完全相等;
      console.log(Object.is(NaN,NaN));//true
      console.log(Object.is(0,-0));//false
  • 2.Object.assign(target, source1, source2..)

    • 将源对象的属性复制到目标对象上
      let obj = {name:'kobe',age:39};
      let objn = {sex:'男'};
      let obj1 ={};
      let obj2 = {};
      Object.assign(obj1,obj.name);
      console.log(obj1);//{0: "k", 1: "o", 2: "b", 3: "e"}
      //将后两个对象,复制到第一个参数对象上。可以复制多个。
      Object.assign(obj2,obj,objn);
      console.log(obj2);//{name: "kobe", age: 39, sex: "男"}
  • 3.直接操作 proto 属性

    let obj3 = {name : 'anverson', age : 41};
    let obj4 = {};
    obj4.__proto__ = obj3;
    console.log(obj4, obj4.name, obj4.age);//{} "anverson" 41

Set和Map数据结构

  • 1.Set容器 : 无序不可重复的多个value的集合体
    • Set()
    • Set(array);
    • add(value);增加指定项
    • delete(value);删除指定项
    • has(value);是否含有
    • clear();清空
    • size;set容器内容长度
var set1 = new Set(['a','f',2,5,1]);
console.log(set1);//Set(5) {"a", "f", 2, 5, 1}
console.log(set1.size);//5
//删除指定项
set1.delete(1);
console.log(set1);//Set(4) {"a", "f", 2, 5}
//检查是否含有指定项
console.log(set1.has(2));//true
console.log(set1.has(1));//false
//增加指定项
set1.add('sd');
console.log(set1);//Set(5) {"a", "f", 2, 5, "sd"}
//清空指定项
set1.clear();
console.log(set1);//Set(0) {}
  • 2.Map容器 : 无序的 key不重复的多个key-value的集合体
    • Map()
    • Map(array)
    • set(key, value)//添加
    • get(key);获得
    • delete(key);删除
    • has(key);判断是否有
    • clear();清除
    • size
let map = new Map([['abc',12],[56,'fre']]);
console.log(map);//Map(2) {"abc" => 12, 56 => "fre"}
console.log(map.size);//2
map.set('sex','男');
console.log(map);//Map(3) {"abc" => 12, 56 => "fre", "sex" => "男"}
console.log(map.get('abc'));//12
map.delete('sex');
console.log(map);//Map(2) {"abc" => 12, 56 => "fre"}
console.log(map.has('sex'));//false
console.log(map.has(56));//true
map.clear();
console.log(map);//Map(0) {}

遍历

  • for(let value of target){}循环遍历
    • 1.遍历数组
    • 2.遍历Set
    • 3.遍历Map
    • 4.遍历字符串
    • 5.遍历伪数组
//遍历数组
let arr = [1,2,3,4,5];
for(let num of arr){
    console.log(num);//1到5依次输出
}
//遍历set
let set = new Set([1,2,3,4,5]);
for(let num of set){
    console.log(num);//1到5依次输出
}
//遍历字符串
let str = 'abcdefg';
for(let num of str){
    console.log(num);//a到g依次输出
}
//遍历伪数组
let btns = document.getElementsByTagName('button');
for(let btn of btns){
    console.log(btn.innerHTML);//按钮1、按钮2、按钮3
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值