ECMAScript 学习小结

ECMAScript和JavaScript的关系是什么?

  前者是后者的规格,后者是前者的一种实现。日常场合,两者是可以互换不做分别的。

    ECMAScript 6 即是ECMAScript的第 6 个版本。

 

let和const命令

  let和const命令:

    let用来声明变量,用法类似于var,但是也有很大的差别。

      const用来声明常量,常量是必须声明后立即赋值的,不可以后续赋值也不可以后续更改值,

        否则会报错。const的其他特点和let基本一致。

          let的变量声明和赋值是同步进行,是不会提前声明的,不挂载到window上的,

            在let声明执行之前也是不可以对let声明的变量进行任何操作的。

 

console.log(b);     //2    
console.log(a);     //报错,提示a不存在

let a = 1;
var b = 2;

 

    let、const声明的变量名不可以重复声明。

let a = 1;
var a = 2;
//直接报错

let a = 1;
function a(){
    var a = 2;
}
//直接报错

    let、const声明只在let命令所在的代码块内有效。

{
    let a = 10;
    var b = 1;
}

console.log(b);      //1
console.log(a);      //报错

    for循环中循环表达式很适合用let命令。也进一步证明let命令只在代码块中有效。

for(var i=0;i<10;i++){}
console.log(i)      //10

for(let j=0;j<10;j++){}
console.log(j)      //报错

    

var a = [];
for (var i = 0; i < 10; i++) {
    a[i] = function () {
        console.log(i);
    };
}
a[6]();       //10     

    以上代码因为var为全局变量赋值,在全局范围内有效且只有一个i,每一次循环i的值都会发生改变,最终累加到10停止循环。

      而for循环内部的console.log( i ),这里的i值在函数内找不到就只能去父级寻找,最终找到已经累加到10的i,进行输出,所以输出为10。

        那么怎样才能使其输出对应下标里的i值呢?

var a = [];
for (let i = 0; i < 10; i++) {
    a[i] = function () {
        console.log(i);
    };
}
a[6]();  //6

    以上代码使用了let来声明变量i,所以i只在块级作用域内有效,而且是本轮循环内有效,所以每次循环的i值都为在一个块级作用域内一个独立的变量。

      而每次循环i能记住上一个i的值,是因为JavaScript内部进行的操作,引擎内部会记住上一轮循环的值,在上一轮循环的基础上进行计算。

        除了上一种方法,还有一种采用闭包的方法。

var arr = [];
for (var i = 0; i < 10; i++) {
    (function(i){
        arr[i] = function(){
        console.log(i)
        }
    }(i))
}
arr[8]();      //8

    let和const的临时死区

      只要块级作用域内存在let和const命令,它所声明的变量就绑定这个区域,不再受外部的影响。

 

ES7中的...运算符

  多用于调用函数和对象:

function abc(a,b,c){
  console.log(a+b+c);
}
var arr = [3,4,5];
abc(...arr)

  该运算符将一个数组变为参数序列。运算符也可以和正常的函数参数结合使用。

function abc(a,b,c,d){
    console.log(a+b+c+d);
}
var arr = [3,4,5];
abc(2,...arr);

   可以通过该运算符来达到克隆的效果。

    浅克隆:

let a = {
    num : 1 
}
let b = {
    num : 2
}
let c = {
    ...a,
    ...b        
}    

    深克隆

let a = {
    num : 1 
}
let b = {
    num : 2
}
let c = {
    num : {
        ...a,
        ...b
    }     
}  

 

解构赋值

  解构一个数组

let arr = [1,2,3];
let x,y,z;
[x,y,z] = arr;
//x = 1;y = 2;z = 3;

 

  解构一个对象

let obj = {
    name : "Tom",
    age : 18,
    sex : "0"
}
let name,age,sex;
({name,age,sex} = obj )
//name = "Tom";age = 18;sex = "0";

箭头函数

  ES6 允许使用“箭头”(`=>`)定义函数。可以非常简洁的写函数。

var sum  = function(a,b){
    return a+b;  
}
//等同于
let sum  = (a,b) =>{
    return a+b;  
}
var fun = function(a,b){
    return {
        a:a,b:b
    }
}
//等同于
let fun = (a,b) => {
    return {
        a : a,
        b : b 
    }
}        
function fun(x){
    return function(y){
        return function(z){
            return x+y+z;
        }
    }
}        
//等同于
let fun = x => y => z => x+y+z;

 

Map 结构

  Map数据结构类似于对象,就是用来存储内容的。

    首先来用Map方法来创建一个集合。

var map = new Map();
map.a = 1;
map.b = 2;
map.c = 3;
map.set("0","html");
map.set("1","css");
map.set("2","JavaScript");

map.get("0");//"html"
map.get("0");//true

 

     这个map数据集合可以使用set方法为其中添加一个键值,也可以用get方法获取到这个值。也可以使用delete方法来删除选择的键值。

 

  作为构造函数,Map也可以接受一个数组作为参数。

var map = new Map([['name','张三'],['age','20']]);
//等同于set('name','张三');

 实例的属性和操作方法

  size属性

    size属性返回Map结构的成员总数

let map = new Map();
map.set("name","Tom");
map.set("age","20");

map.size    //2

  Map.set(key,value)

    set方法设置属性名key对应的属性值为value,然后返回整个Map结构。如果key已经有值,则属性值会被更新,否则就新生成该属性。

let map = new Map();

map.set("key",10);    //属性名是字符串,值为数字
map.set(110,"120");    //属性名是数字,值为字符串
map.set(undefined,"haha")    //属性名为undefined,值为字符串

//可以使用链式写法
map.set(1,"a")
  .set(2,"b")
  .set(3,"c");

  Map.get(key)

    get方法读取key对应的属性值,如果找不到key,则返回undefined

function fun(){console.log("Hello world!!!");}
let map = new Map()
    .set(fun,"Hello");

map.get(fun);    //会调用到该函数,输出"Hello world !!!"
map.get(haha);  //undefined

  Map.delete(key)

    delete方法删除某个属性,返回true。如果删除失败,则返回false

function fun(){console.log("Hello world !!!");}
let map = new Map().set(fun,"Hello world")

map.delete(fun);    //true
map.delete(fun);    //false

  Map.clear()

    clear方法清除所有成员,没有返回值。

let map = new Map();
map.set(1,1);
map.set(2,2);

map.clear();

Map的循环遍历

  for of

var map = new Map([['name','张三'],['age','20']]);
//等同于set('name','张三');
for(var i in map){
    console.log(i)
}
//输出map对象下标名
for(var index of map){
    console.log(index);
}
//输出添加进去的键值对的数组
for(var name of map.entries()){
    console.log(name)
}
//输出对应的键值对
for (var [key,value] of map.entries()){
    console.log(key,value)
}
//输出对应键值对
for (var val of map.values()){
    console.log(val)
}
//输出键值对的值

 

class

  ES 6 的类完全可以看做构造函数的另一种写法。其数据类型就是函数。

class Hyh{}
typeof Hyh; //"function"

  使用的时候也是直接对lei使用new命令,和构造函数的用法完全一致。

class ID{
    constructor(name,age){
        this.name = name;
        this.age = age;  
    }
    logFun(){
        console.log("name:"+this.name+"\n"+"age:"+this.age);
    }
}

var Tom = new ID("Tom",21);
Tom.name    //"Tom"
Tom.age    //21

Tom.logFun();     
//name:Tom
//age:21

  Tom是ID的实例,Tom的constructor方法就是ID类原型的constructor方法,可以在类的prototype上添加类的新方法。可以通过Object.assign方法一次向类添加多个方法。

Object.assign(ID.prototype,{
    toName(){},
    toAge(){} 
})

class的继承

  class可以通过extends关键字实现继承

class Code extends ID{}

  继承后可以调用继承来的方法和属性

var Jack = new Code("Jack","20");
Jack.name;    //"Jack"
Jack.logFun();
//name:Jack
//age:20

  也可以继承父类函数后再在自身添加新的属性和参数,通过super方法接收父类构造的参数信息

class ID{
    constructor(name,age){
        this.name = name;
        this.age = age;  
    }
    logFun(){
        console.log("name:"+this.name+"\n"+"age:"+this.age);
    }
}

class Code extends ID{
    constructor(name,age,color){
        super(name,age);    //用来继承父类参数接收
        this.color=color
    }
}

var color = new Code("Jack","20","black")


Promise对象  承诺

  它是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。主要用来做异步的消息处理的。

  它就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。Promise提供统一的API,各种异步操作都可以用同样的方法进行处理。

Promise对象的两个特点:

  1、对象的状态不受外界的影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、funlfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。

  2、一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为funlfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就成为resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果,这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。

基本用法

  Promise对象是一个构造函数,用来生成Promise实例。

let promise = new Promise(function(resolve,reiect){
    if("如果异步操作成功"){
        resolve(value);    //执行resolve成功函数
    }else{
        reject(error);    //执行reject失败函数
    }
})

  Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve失败函数和reject成功函数。它们是两个函数,由JavaScript引擎提供,不用自己部署。

  resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从pending变为resolved),再异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从pending变为rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

then()方法

  Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的毁掉函数。

promise.then(function(value){
    console.log("成功了!"+value);
},function(error){
    console.log("失败了!"+error);
})

  then调用以后又返回一个Promise对象。这时可以链式写法在新的Promise上写then方法,这个then方法指定的回调函数,就会等待这个新的Promise对象状态发生变化。

promise.then(function(data){
    return data + 10;
},function(){
}).then(function(data){
    console.log(data);
},function(err){
    console.log(err); 
})

  利用Promise写一个ajax

var btn = document.getElementById("btn");
var box = document.getElementById("box");

btn.onclick = function(){
    var promise = new Promise(function(resolve,reject){
        ajax('./16.txt',function(data){
            resolve(data)
        },function(err){
        reject(err)
        })
    })
    promise.then(function(data){
        box.innerHTML = data;
    },function(err){
        box.innerHTML = err;
    })
}

function ajax(url,fnSucc,fnErr){
    var xhr = new XMLHttpRequest();
    xhr.open('GET',url,true);
    xhr.send();
    xhr.onload = function(){
        if(xhr.readyState == 4 && xhr.status == 200){
        fnSucc(xhr.responseText);
        }else{
        fnErr(xhr.status);
        }
    }
}        

 

   

 

上一篇:ECMAScript 6.0


下一篇:JavaScript简介