Giter Site home page Giter Site logo

silencehvk / silencehvk.github.io Goto Github PK

View Code? Open in Web Editor NEW
1.0 1.0 0.0 58.81 MB

:books: :octocat: 个人博客,博客地址:https://blog.hvkcoder.me

Home Page: https://silencehvk-github-io.vercel.app

License: MIT License

HTML 33.45% CSS 15.33% JavaScript 51.22%
blog blog-theme vuejs

silencehvk.github.io's Introduction

silencehvk.github.io's People

Contributors

silencehvk avatar

Stargazers

 avatar

silencehvk.github.io's Issues

【JavaScript ES6】2.Destructuring (解构)

数组基本用法

  ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为 解构(Destructuring)

    var [a, b, c] = [1, 2, 3]; 
    console.log(a, b, c); // 1 2 3

以上代码表示,可以从数组中直接提取值,按照对应的位置,对应变量赋值。只要两边等号的模式相同,左边的变量就会被赋予对应的值,我们称为模式匹配。如果解构不成功,变量的值就等于 undefind

  等号左边模式,只要匹配一部分的等号右边的数组。这种情况下,解构依然成功,我们称为不完全解构

    var [x, y] = [1, 2, 3];
    console.log(x, y); // 1 2

  如果等号右边不是数组(或者严格地说,不是可遍历的结构)。这种情况,结构将会报错

    var [foo] = 1;

  结构赋值不仅适用于 var 命令,也适用于 let 和 const 命令

    let [x ,...y] = ['Hello' ,'ES6'];
    console.log(x, y); // Hello ['ES6']

    const [APPID,SECRET] = ['Destructuring','ESCMAScript6'];
    console.log(APPID, SECRET); // Destructuring ESCMAScript6

  对于 Set 结构,也可以使用数组解构赋值

    let [x, y, z] = new Set(['Hello' , 'ESCMAScript6','World']);
    console.log(x, y, z); // Hello ESCMAScript6 World

  事实上,只要某种数据结构具有 Iterator 接口,都可以采用数组形式写解构赋值,如 Generator函数 :

    function* fibs(){
        let a = 0;
        let b = 1;
        while(true){
            yield a;
            [a, b] = [b , a + b];
        }
    }

    var [first, second, third, fourth, fifth, sixth] = fibs();
    console.log(sixth); // 5

默认值

  解构赋值允许指定默认值

    var [defaultValue = 10] = [];

  ES6 内部使用严格相等运算符( === ),判断一个位置是否有值。如果一个数组成员不严格等于 undefined,默认值是不会生效的

    var [defaultValue = 10] = [null];
    console.log(defaultValue); // null

  如果默认值是一个表达式,那么这个表达式是惰性求值,即只有在用到的时候,才会求值

    var f = function(){
        return 20;
    }
    //没有用到 表达式
    var [defaultValue3 = f()] =[1];
    console.log(defaultValue3); // 1

    //用到 表达式
    var [defaultValue4 = f()] =[];
    console.log(defaultValue4); // 20

  默认值可以引用解构赋值的其他变量,但是这个变量必须已经声明

    var [defaultValue5 = 1, defaultValue6 = defaultValue5] = [];
    console.log(defaultValue5,defaultValue6);// 1 1

对象的解构赋值

  解构不仅可以用于数组,还可以用于对象

    var {foo , bar} = {foo : 'aaa', bar : 'bbb' };
    console.log(foo, bar);// aaa bbb

对象解构与数组解构不同,数值解构是按照数组次序进行取值;对象解构是按照属性名取值,即变量名与属性名相同。

  如果变量名与属性名不相同时,必须写成以下方式

    var {foo : baz} = { foo :'Hello'};
    console.log(baz);// Hello

对象的解构赋值的内部机制,是先找到同名的属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。

  变量的声明与赋值是一体的。对于let和const来说,变量不能重新声明,所以一旦赋值的变量以前声明过,就会报错。

    let foo;
    let {foo} = {foo:1}; // SyntaxError: Duplicate declaration "foo"

  解构也可以用于嵌套解构的对象

    var obj = {
        p:[
            "Hello",
            { world : "World" }
        ]
    };
    var { p :[hello,{world}]} = obj;
    console.log(hello,world); // Hello World

这时 p 是模式,不是变量,因此不会被赋值

字符串的解构赋值

  字符串也可以解构赋值。这是因为此时字符串被转换成了一个类似数组的对象

    const [H, E, L, L2, O] = 'hello';
    console.log(H,E,L,L2,O);// h e l l o

  类似数组的对象都有一个 length 属性,因此还可以对这个属性解构赋值

    let { length } = 'hello';
    console.log(length); // 5

用途

  1. 交换变量的值
    [x, y] = [y, x];
  1. 从函数返回多个值
    var example = function(){
        return ['hvkcoder', 18, 'coder'];
    };
    var [name, age, job] = example();
  1. 函数参数的定义
    //有次序的值
    function func([firstParm,secondParm]){
        console.log(firstParm,secondParm); // Hello World
    }
    func(['Hello','World']);

    //无次序的值
    function funcNo({userName,passWorld}){
        console.log(userName,passWorld);    // hvkcoder 1234
    }
    funcNo({userName:'hvkcoder',passWorld:'1234'});
  1. 提取 JSON 值,解构赋值对提取 JSON 对象中的数据,尤其有用
    var jsonData = {
        id: 1,
        data: [1,2]
    };
    let { id,data} = jsonData;// 1 [ 1, 2 ]
  1. 遍历Map结构
    var map = new Map();
    map.set('first','hello');
    map.set('second','world');
    for(let [key, value] of map){
        console.log(key + ':' + value); // first : hello second : world
    };
    //获取键
    for(let [key] of map){};

    //获取值
    for(let [,value] of map){}

小结

  利用var,let结合数组解构,可以一次声明多个变量。特别是json数据的提取和变量的转换上,以及函数的默认参数传递上可以给默认值。解构赋值允许指定默认的值,有效的解决了函数返回多个变量的赋值问题,同时也解决了函数参数默认值的问题。

【JavaScript ES6】1.let 和 const 命令

let 命令

  ES6新增了 let 命令,用来声明变量。它的用法类似于 var,但是所声明的变量,只能在 let 命令所在的代码块内有效。

    {
        var a = 10;
        let b = 1;
    }
    console.log(a);//10
    console.log(b);//ReferenceError: b is not defined.

  let 不像 var 那样会发生 “变量提升” 现象。所以,变量一定要在声明后使用,否则会报错。

    console.log(foo);// undefined
    var foo = 2;

    console.log(bar);//ReferenceError: bar is not defined
    let bar = 2;

  ES6 明确规定,如果区块中存在 let 和 const 命令,这个区块对这些命令声明的变量从一开始就形成了封闭作用域,这些变量将不受外界影响,凡是在声明前就使用这些变量,就会报错。这种语法我们称为 “暂时性死区(temporal dead zone 简称 TDZ)”

    var tmp = 123;
    if (true) {
        tmp = 'abc'; // ReferenceError: tmp is not defined  
        let tmp;
    }

TDZ 也就意味着 typeof 不再是一个百分百安全的操作。

    console.log(typeof testType); //ReferenceError: testType is not defined
    let testType;

TDZ 的本质就是:只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量

  let 不允许在同一个作用域中,重复声明相同的变量

    //报错
    function func(parm){
        let parm = 'Hello';//SyntaxError: Identifier 'parm' has already been declared
    };

    //不报错
    function func2(parm){
        {
            let parm = 'Hello';//Hello
        }
    };

块级作用域

  为什么需要块级作用域?

  • ES5 只有全局作用域和函数作用域,没有块级作用域,这样会带来很多不合理的场景

    • 第一种场景,内层变量可能会覆盖外层变量
        var scop_one = new Date();
        function showScopOne(){
            console.log(scop_one);
            if(false){
                var scop_one = 'Hello World';
            }
        };
        showScopOne(); // undefined

    上面代码中,执行 showScopOne 函数输出结果为 undefined,原因在于变量提升,导致内层的 scop_one 变量覆盖了外层的 scop_one 变量。

    • 第二种场景,用来计数的循环变量泄露为全局变量
        var scop_two = 'Hello';
        for(var i = 0; i< scop_two.length; i++);
        console.log(i); //5

    变量 i 只用来控制循环,但是循环结束后,它并没有消失,泄露成了全局变量。

  • ES6 let 命令为 javascript 新增了块级作用域

    • 实际上使得获取广泛应用的立即执行匿名函数(IIFE)不再必要了
        //IIFE 写法
        (function(){
            var temp = ....
        })();
    
        //块级作用域写法
        {
            let temp = ....
        };
    • ES6 明确允许在块级作用域中声明函数
        'use strict';
        if(true){
            function f(){};
        };
    • 并且 ES6 规定,块级作用域中,函数声明的语句类似于 let命令,在块级作用之外不可引用
        function foo() { console.log('I am outside!'); }
        (function(){
            if(false){
                function foo(){console.log('I am inside!'); };
            }
            foo(); //I am outside!
        });

const 命令

  const 命令声明了一个只读的常量,一旦声明,常量的值不能改变。这也就意味着,const 一旦声明,就必须立即初始化赋值。

    const PI = 3.1415;
    PI = 3; //TypeError: Assignment to constant variable.

   const 的作用域与 let 命令相同,只在声明所在的块级作用域内有效。

    {
        const SECRET = 'Hello Const';
    };
    console.log(SECRET); //SECRET is not defined

   const 命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用,同样也不能重复声明。

  const 命令声明的对象是可以更改其属性值的。

    const USER = {
        name:'H_VK'
    }
    USER.password = '123456';
    console.log(USER);// {name: "H_VK", password: "123456"}

这是因为对象是引用类型,const 只针对其引用的内存地址不可更改,而不针对其属性值更改。

小结

  let 用来声明块级变量,当一个变量已经用let声明了,当我们再次用let或var进行声明就会报错。块级{}中的let只在快中有效。在es6 中 var,let可以一次性声明多个变量,对象或数组的格式为多个变量赋值。

  关于常量的声明const,可以一次性声明多个常量,const声明一个只读的常量。一旦声明,常量的值就不能改变。但对于声明的常量是一个字面量的对象时,是可以修改常量的属性值。

【JavaScript ES6】3.Promise 的使用

Promise 的作用

  Promise 用于异步计算,可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果。

  可以在对象之间传递和操作 Promise,帮助我们处理队列。

Promise 的声明

  new Promise(function(resolve,reject){
      resolve(); // 数据处理完成
      reject(); //数据处理出错
  }).then(function(res){
      // 成功数据 res
  },function(error){
      // 处理错误 error
  });
  • Promise 是一个代理对象,它和原先要进行的操作并无关系。
  • Promise 将回调函数改为链式调用解决回调地狱问题。

Promise 的状态

  一个 Promise 可能有三种状态:

  • 等待(pending):初始化一个 Promise 对象时。
  • 已完成(fulfilled):操作成功时。
  • 已拒绝(rejected):操作失败时。

一个 Promise 状态只可能从“等待”转到“完成”或“拒绝”,不能逆向转换,同时“完成”和“拒绝”不能相互转换。

  当 Promise 状态发生改变,就会触发 then 函数。

  then函数接受两个参数,第一个参数是成功时的回调,在 Promise 由“等待“状态转换到”完成“状态时调用;第二个参数是失败时回调,在 Promise 由“等待”状态转换为“拒绝”状态时调用。

  then可以接受另加一个 Promise 传入,也接受一个 “类then” 的对象或方法,即 thenable 对象。

  同一个 Promise 的 then 可以调用多次,并且回调的执行顺序跟它们被定义的顺序一致。

Promise 常用的函数

Promise.then()

  • Promise.then() 接受两个函数作为参数,分别代表 fulfilled 状态下的响应函数 和 rejected 状态下的响应函数。
  • Promise.then() 返回一个新的 Promise 实例,所以支持链式调用。
  • Promise 状态发生改变时,Promise.then() 会根据其返回的最终状态,调用相应的响应函数。
  • Promise.then() 中可以返回一个新的 Promise 或其他值。
  • 如果返回值为新的 Promise 时,那么下一级 Promise.then() 会在新的 Promise 状态改变后执行。
  • 如果返回值为其他值,那么下一级 Promise.then() 会立即执行。

在嵌套 Promise.then()时 ,由于 Promise.then() 返回的还是一个 Promise,所以下一级的 Promise.then() 会等到里面的 Promise.then() 执行完后再执行。

Promise.catch()

  Promise.catch()Promise.then(resolve,reject)reject 的别名,用于指定发生错误的回调函数。用法如下:

    new Promise((resolve,reject)=>{
    
    }).then(res=>{
        
    }).catch(error=>{
        
    });

Promise.catch() 也会返回一个 Promise,并且其状态也为 pending

reject 的作用等同于抛出一个异常。如果 Promise 状态已经变成 resolved ,再抛出错误是无效的

Promise.finally()

  Promise.finally() 是用于指定无论 Promise 最终状态如何,都会执行的操作,是在 ES2018 中引入的。用法如下:

    new Promise((resolve,reject)=>{
    
    }).then(res=>{
        
    }).catch(error=>{
        
    }).finally(()=>{
        
    });

Promise.finally()方法的回调函数不接受任何参数,因此Promise.finally()方法里面的操作,与Promise的状态无关。

Promise.finally() 本质上是 Promise.then() 的特例,Promise.finally() 方法总是会返回原来的值。

Promise.all()

  Promise.all 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。使用方法如下:

    new Promise.all([p1,p2,p3]);

Promise.all 的参数可以不是数组,但参数必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。

  Promise.all 的状态由传入的参数决定,分为两种情况:

  • 当数组中所有 Promise 状态完成,该 Promise 才算完成,其返回结果为全部值的数组。
  • 当其中任何一个失败,该 Promise 则失败,此时第一个被 reject 的实例的返回值。

Promise.race()

  Promise.race 方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。使用方法如下:

    new Promise.race([p1,p2,p3]);

只要参数中的任何一个状态更改,其返回结果则为率先改变的 Promise 实例。

Promise.resolve()

  Promise.resolve 方法可以将现有对象转为 Promise 对象,如下:

    const jsPromise = Promise.resolve($.ajax('/whatever.json'));

  Promise.resolve 方法的参数分为四种结果:

  • 参数是一个 Promise 实例
      Promise.resolve将不做任何修改,原封不懂的返回。

  • 参数是一个 thenable 对象

  thenable 对象指的是具有 then 方法的对象,如下:

    const thenable = {
        then: function(resolve,reject){
            resolve();
        }
    };

Promise.resolve 会将这个方法转为 Promise 对象然后立即执行 thenable 对象中的 then 方法。

  • 参数不是具有 then 方法的对象,或根本就不是对象
      Promise.resolve 会返回一个新的 Promise 对象的实例,其状态为 fulfilled

  • 不带有任何参数
      Promise.resolve 方法允许调用时不带参数,它回直接返回一个状态为 fulfilledPromise 实例。

Promise.reject()

   Promise.reject 也会返回一个 Promise 实例,状态为 rejected

     const jsPromise = Promise.reject('Error');

Promise.try()

   Promise.try就是模拟 try 代码块。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.