Javascript基础语法

以下更新于2021年


JavaScript的概述

什么是Javascript

JavaScript是运行在JavaScript解释器/引擎中的解释脚本语言
详细使用,参考文档:https://www.w3school.com.cn/js/index.asp
运行环境:

  • 独立安装的js解释器(NodeJS
  • 嵌入在浏览器内核中的JS解释器

JS有三大组件:

  • 核心ECMAScript
  • 文档对象模型DOM,Document Object Model)与网页对话
  • 浏览器对象模型BOM,Browser Object Model )与浏览器对话

JS特点:

  • 开发工具简单,记事本即可
  • 无需要编译,直接由JS引擎负责执行
  • 弱类型语言,由数据决定数据类型
  • 面向对象

JS脚本在HTML页面调用的三个位置:(允许调用放在页面的任何位置)

  • 嵌入在元素”事件”中
    <html>
      <body>
          <button onclik="console.log("Hello World");" >打印消息</button>
      </body>
    </html>
    
  • 嵌入在<script>标签中
    <html>
      <script>
          document.write('<b>欢迎</b>');
          console.log('结束');
      </script>
      <body></body>
    </html>
    
  • 将JS代码写在外部的脚本文件中(xx.js)
    <html>
      <!-- 外部文件调用 -->
      <script src="js文件路径xxxx.js">这里面不允许出现任何内容,不会被执行</script>
      <body></body>
    </html>
    

语法规范:

  • 用 ‘ ; ‘ 结束语句
  • 大小写敏感
  • 注释为/ /

一些例子:

//ECMAScript 嵌入标签中示例
<script>
    var a = [1,2,3,4];  /*数组*/
    var sum = 0;
    for(var i = 0; i < a.length ; i++){
        sum += a[i];
    }
    document.write(sum);
</script>
//DOM嵌入元素事件示例
<div>
    <p id = "yuyu">改变样式</p>
    <!-- 当点击事件发生时,js回找到ID为yuyu的标签,并通过.style下的方法去改变其属性 -->
    <button onclik="document.getElementById('yuyu').style.fontSize='24px'">点击改变字号</button>
</div>
//BOM嵌入标签示例
<script>
    function load()
        window.open('http:www.baidu.com','_blank','width=600,height=400,top=100px,left=0px')
    }
</script>
<button onclik="load()">百度</button>

基础语法

变量

var name;        //定义变量未赋初值
var book = 25.5  //定义变量赋初值25.5
var name, book = 5, se = 10;  //多定义
allvar = 1;      //全局变量
//尽量用var去声明,全局变量危害众多


//关键字
break case catch continue default
delete do else false finally
for function if in instanceof
new null return switch this
throw true try typeof var
void while with undefined

一些例子:

//ECMAScript 嵌入标签中示例
<script>
    var stuName = "你好";
    console.log(stuName);   //在浏览器上输出打印
</script>

数据类型

原始数据类型:数字类型、字符串类型、布尔类型、空、未定义
number:

  • 和其他语言一样,整数32位占4字节,浮点数64位占8字节。
    var n = 123;
    var t = 0x80;
    var nf = 4.5e10;
    

String:

  • 和其他语言一样,由Unicode编码字符、数字、标点组成。一个字符内存占2字节
    `javascript
    “张”.charCodeAt().toString(16); //字符串转16进制

    0x5f20

汉字的起始字符串: \u4e00 - \u9fa5


**boolean:**
- 和其他语言一样
```javascript
var b = true    //非0及1,非真即假

空:

  • 和其他语言一样 null

未定义:

  • 和其他语言一样 undefined

弱类型语言:

//由数据来决定变量的数类型
var stu;    //undefined
var stu = 25; //number
var stu = "123"; //string
var res = 123 + "123";  //string

注:所有数据类型和string做+运算时,结果都为string类型

隐式转换

//typeof( ) 或者 typeof来获取数据类型
var num = 15;
var s = typeof(num);  或者 
var s = typeof num ;

//NaN   判断数据是否是非数字
var num = 15;
isNaN(num);   //true为非数字,false为数字

强制类型转换toString:

变量.toString();

转换函数:

//parseInt(); 获取指定数据的整数部分
var result = parseInt(数据);

//parseFloat()  将指定数据转换成小数var 
var result = parseFloat(数据);

//Number(); 将字符串解析成number
var result = Number(数据);

运算符与表达式

和其它语言基本相同,

=== 为全等,不仅判断数据也会判断类型
!== 不全等。

var num = prompt("请输入一个数据:")
console.log(isNaN(num));  //判断数据类型打印输出

var score = 85;
var result = score >= 80 ? "优秀": (score >= 60 ? "合格" : "不及格");

函数

function 函数(参数列表声明){
    //代码块
}


//声明一个printInfo()的函数
function printInfo(userName,ueserPwd){
    console.log('用户名:'+userName+'密码:'userPwd);
}
//调用函数
printInfo('Tom','123');

//带返回值的函数
function add( num1 , num2 ){
    return num1 + num2;
}
//调用函数
var res = add(10,20)

作用域通用

声明提前:
JS在正式执行之前,会将所有var声明的变量和function声明的函数,预读到所有作用的顶部,但是,对变量的赋值(比如add(a),会连同a也会被提前声明),还是保留在原来的位置。

分支循环结构

与C无异同
while循环 和 do-while

//不再多赘述
while(boolean表达式){
    语句;
}

do{
  语句;
}while(boolean表达式);

for循环

//不再多赘述
for(表达式,表达式,表达式){
    语句;
}

if-结构

//不再多赘述
if(表达式){
    语句;
}

if-else结构

//不再多赘述
if(表达式){
    语句;
}else{
    语句;
}

switch结构

//不再多赘述
switch(表达式){
    case 数值1: 语句1;
        break;
        ...
    case 数值n: 语句n;
        break;
    default:语句n;break;
}

示例:购物车结算程序

<!doctype html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
    </head>
    <body>
        <script type="text/javascript">
            // 根据商品单价、购买数量以及收款金额计算并输出应收金额和找零。
            // 当总价大于或等于500时,享受8折优惠。
            // 如果收款小于应收款,给出提示


                //1、定义输入变量:单价(price),数量(count),收款金额(money)
                // 破ruai斯
                var price,count,money;
                //2、定义输出变量:产品总价(total),找零(change)
                // tou tou
                var total,change;
                //3、为输入变量赋值(prompt方式)
                    //3.1 为 单价(price) 赋值
                    price=prompt("请输入商品单价:");
                    //3.2 为 数量(count) 赋值
                    count=prompt("请输入购买数量:");
                //4、根据 单价 和 数量 ,计算 产品总价(total) total = price * count ,输出产品总价
                total=price*count;

                /********增加条件判断:大于500打八折*********/
                /*条件:total>=500?*/
                /*满足:total*=0.8 */
                if(total>=500){
                    alert("您消费超过500,可以打八折");
                    total*=0.8;
                }
                alert("您此次消费:"+total+"元");
                //5、为收款金额(money)赋值 (prompt)
                money=prompt("收款:");

                /*********判断 应收金额(total)和收款金额(money)之间的关系***********/
                if(money>=total){
                    //6、计算找零(change)=收款金额(money)-产品总价(total),输出找零
                    change=money-total;
                    alert("共找您:"+change+"元");
                }else{
                    alert("对不起,您给的钱不够!!!");
                }
        </script>
    </body>
</html>

数组

三个不限制:

  • 不限制数组的元素个数:长度可变
  • 不限制下标越界
  • 不限制元素的数据类型
//数组定义
var arr=[]    //直接定义
var arr = [123,456,789];
var arr = new Array();   //用new声明
var arr = new Array(10);   //长度为10
var arr = new Array("tom","mark","john");   //用new声明

//数组操作
arr[0] = '三国志';
arr[1] = 123;
arr[2] = true;

console.log(arr[2]);   //打印

console.log(arr.length)  //打印arr的大小

关联数组
类似键值对

var bookInfo =[];
bookInfo['bookName'] = '西游记';
bookInfo['price'] = '35.5';

//遍历关联数组
for(var key in hash){
    key  //元素的下标
    hash[key]  //当前元素值
}

1、String( arr ):将arr中的每个元素转为字符串,用逗号分隔。
2、数组.join("连接符"):将数组中每个元素之间用连接符拼接成字符串,

1、将字符组成单词
var chars=["H","e","l","l","o"];
console.log(chars.join(""));
>Hello

//判断数组是否是空数组
数组.join("") == ""

2、将单词组成句子:words.join("");
3、将数组转化为页面元素的内容:
    "<开始标签>"+
    arr.join("</结束标签><开始标签>")
    +"</结束标签>"

3、concat()拼接两个货多个数组,并返回结果。

var arr0 = [];
var arr1 = [80,90];
var arr2 = [40,4,3];
var arr4 = arr0.concat(50,60,arr1,arr2);
//将值60、50和数组arr1、arr2中的元素值,都拼接到arr0中,其它数组值不变

//slice()
var subArr = arr.slice(starti,endi+1)
//选取arr中starti位置开始,到endi结束的所有,元素组成新数组返回-元素组保持不变。

1、一直选取到结尾,可省略第二个参数
2、如果选取的元素离结尾近:可用倒数下标
3、复制数组:
arr.slice(0,arr.length);
    可简写为:arr.slice();

4、修改数组splice(),直接修改原数组

数组.splice(starti,n);
删除arr中starti位置开始的n个元素不考虑含头不含尾

数组.splice(starti,0,1,2,...);
在arr中starti位置,删除0个元素,开始插入新值1,值2....

5、颠倒数组reverse()

var arr = [1,2,3];
arr.reverse();
console.log(arr);
>[3,2,1]

6、排序sort()
默认将所有元素转为字符串在排列

var arr = [1,2,3];
arr.sort();
console.log(arr);
>[3,2,1]

DOM

DOW,document object model,是W3C(万维网联盟)的标准,是中立于平台和语言的接口,它允许程序和脚本动态地访问和更新文档地内容、结构和样式。对网页进行增删改查地此操作。

DOM查找

1、按id属性,精确查找一个元素对象。效率非常高!
var elem=document.getElementById(“id”);

<ul id="myList">
    <li id="m1" >首页</li>
</ul>
<script>
    var ul = document.getElementById('myList');
    console.log(ul);
</script>

2、按标签名找
var elems = parent.getElementByTagName(“tag”);
查找指定parent节点下地所有标签为tag地子节点,返回一个集合。

<ul id="myList">
    <li id="m1" >首页</li>
</ul>
<script>
    var list = ul.document.getElementById('li');
    console.log(list);
</script>

3、通过name属性查找
document.getElementByName(“name属性值”);
可以返回DOM数中具有指定name属性值地所有子元素集合。

<ul id="myList">
    <li id="m1" name="boy" >首页</li>
</ul>
<script>
    var list = document.getElementsByName('boy');
    console.log( typeof list );
</script>

4、通过class查找
parent.getElementsByClassName(“class”);
有兼容性问题:IE9+。

<div id="myList">
    <li class = "sub">首页</li>
</div>
<script>
    var list = div.getElementsByClassName('sub');
    console.log( list );
</script>

5、只找一个元素和多个元素:
var elem = parent.querySelector(“selector”)
selector支持一切css中选择器,如果选择器匹配地有多个,只返回第一个。

var elem = parent.querySelectorAll(“selector”)
selector API返回地是非动态集合。

例子:随机三位验证码

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
    #code{
        width: 100px;
        height: 50px;
        background-color: lightblue;
        font-size: 44px;
        letter-spacing: 5px;
    }
    </style>
</head>


<script>
function createRandCode(){
    var chars=['a','b','c','1','2','3'];  //验证码取自chars元素
    var randcode="";
    for(var i=0;i<3;i++){//3位随机码
        //Math.floor(); 取整
        、、
        var randpos =Math.floor(Math.random() * chars.length);        
        randcode+= chars[randpos];
    }
    document.getElementById("code").innerHTML=randcode;
    //用.innerHTML方法修改id="code"地标签中,输入数值。
}
</script>
<div id="code"></div>
<button onclick="createRandCode()">验证码</button>
</script>

DOM修改

核心DOM的四个指令
1、读取属性值

  • 线获得属性节点对象,在获得节点对象的值:
      var attrNode=elem.attributes[下标/属性名];
      var attrNode=elem.getAttributeNode(属性名);
    
  • 直接获取属性值
      var value = elem.getAttribute("属性名");
    
    2、修改属性值
  • 修改属性值
      elem.setAttribute("属性名",value);
    
  • 判断是否含指定属性

      var bool = elem.hasAttribute("属性值");
    
      //判断ID为b1的有没有onclick属性
      document.getElementById('b1').hasAttribute('onclick');
    
  • 移除属性

      var bool = elem.hasAttribute("属性值");
    
      //移除ID为b1的class属性
      document.getElementById('b1').removeAttribute('class');
    

    3、修改样式
    elem.style.属性名

      类似background-color 要写成 backgroundColor
    

DOM添加

添加元素的步骤:创建空元素、设置关键属性、将元素添加到DOM树。

1、创建空元素
var tr = document.createElement('tr');

2、设置关键属性
tr.innerHTML = "GOOGLE";
tr.herf="http://www.google.com";
tr.style.opacity = "1";
tr.style.cssText = "width:100px;height:100px;";

3、将元素添加到DOM树
div.appendChild(tr);    //将tr添加到div的子节点
div.insertBefore(tr,ul); //将tr添加到div的子节ul之前

注:尽量少操作DOM树,每此修改都会重新layout。

BOM

专门操作浏览器窗口的API,没有标准,有兼容问题。

window:代表整个窗口
history:封装当前窗口打开后,成功访问过的历史url记录
navigator:封装浏览器配置信息
document:封装当前正在加载的网页内容
location:封装了当前窗口正在打开的url地址
screen:封装了屏幕的信息

完整窗口大小:window.outerWidth、window.outerHeight
文档显示区大小:window.innerWidth、window.innerHeight

定时器

1、周期定时器

setInterval(function(){
    console.log("Hello World");
},1000);//毫秒

2、一次定时器

setTimeout(function(){
    alert("123");
},1000);//毫秒

以下更新于2017年


刚开始用vue或者react,很多时候我们都会把ES6这个大兄弟加入我们的技术栈中。但是ES6那么多那么多特性,我们需要全部都掌握吗?秉着八原则,掌握好常有用的这个可以让我们快速起飞

变量声明const和let

我们都是知道在ES6以前,var关键字声明变量。无论声明在何处,都会被视为声明在函数的最顶部(不在函数内即在全局作用域的最顶部)。这就是函数变量提升例如:

function aa() {
    if(bool) {
        var test = 'hello man'
    } else {
        console.log(test)
    }
  }

以上的代码实际上是:

function aa() {
    var test // 变量提升
    if(bool) {
        test = 'hello man'
    } else {
        //此处访问test 值为undefined
        console.log(test)
    }
    //此处访问test 值为undefined
  }

所以不用关心bool是否为true or false。实际上,无论如何test都会被创建声明。

接下来ES6主角登场:

我们通常用let和const来声明,let表示变量、const表示常量。let和const都是块级作用域。怎么理解这个块级作用域?
在一个函数内部,在一个代码块内部,说白了 { }大括号内的代码块即为let 和 const的作用域。
看以下代码:

function aa() {
    if(bool) {
       let test = 'hello man'
    } else {
        //test 在此处访问不到
        console.log(test)
    }
  }

let的作用域是在它所在当前代码块,但不会被提升到当前函数的最顶部。再来说说const。

 const name = 'lux'
    name = 'joe' //再次赋值此时会报错

说一道面试题

var funcs = []
    for (var i = 0; i < 10; i++) {
        funcs.push(function() { console.log(i) })
    }
    funcs.forEach(function(func) {
        func()
    })

这样的面试题是大家常见,很多同学一看就知道输出 10 十次
但是如果我们想依次输出0到9呢?两种解决方法。直接上代码。

// ES5告诉我们可以利用闭包解决这个问题
    var funcs = []
    for (var i = 0; i < 10; i++) {
        func.push((function(value) {
            return function() {
                console.log(value)
            }
        }(i)))
    }
    // ES6
    for (let i = 0; i < 10; i++) {
        func.push(function() {
            console.log(i)
        })
    }

达到相同的效果,ES6简洁的解决方案是不是更让你心动!!!

模板字符串

ES6模板字符简直是开发者的福音啊,解决了ES5在字符串功能上的痛点。

第一个用途,基本的字符串格式化。将表达式嵌入字符串中进行拼接。用${}来界定。

 //es5 
    var name = 'lux'
    console.log('hello' + name)
    //es6
    const name = 'lux'
    console.log(`hello ${name}`) //hello lux

第二个用途,在ES5时我们通过反斜杠()来做多行字符串或者字符串一行行拼接。ES6反引号()直接搞定。

 // es5
    var msg = "Hi \
    man!
    "
    // es6
    const template = `<div>
        <span>hello world</span>
    </div>`

对于字符串es6当然也提供了很多厉害的方法。说几个常用的。

 // 1.includes:判断是否包含然后直接返回布尔值
    let str = 'hahay'
    console.log(str.includes('y')) // true
    // 2.repeat: 获取字符串重复n次
    let s = 'hh'
    console.log(s.repeat(3)) // 'hehehe'
    //如果你带入小数, Math.floor(num) 来处理

函数

函数默认参数

在ES5我们给函数定义参数默认值是怎么样?

 function action(num) {
        num = num || 200
        //当传入num时,num为传入的值
        //当没传入参数时,num即有了默认值200
        return num
    }

但细心观察的同学们肯定会发现,num传入为0的时候就是false, 此时num = 200 与我们的实际要的效果明显不一样

ES6为参数提供了默认值。在定义函数时便初始化了这个参数,以便在参数没有被传递进去时使用。

 function action(num = 200) {
        console.log(num)
    }
    action() //200
    action(300) //300

箭头函数

ES6很有意思的一部分就是函数的快捷写法。也就是箭头函数。

箭头函数最直观的三个特点:

  • 不需要function关键字来创建函数
  • 省略return关键字
  • 继承当前上下文的 this 关键字

//例如:
    [1,2,3].map( x => x + 1 )

//等同于:
    [1,2,3].map((function(x){
        return x + 1
    }).bind(this))

说个小细节。

当你的函数有且仅有一个参数的时候,是可以省略掉括号的。当你函数返回有且仅有一个表达式的时候可以省略{};例如:

 var people = name => 'hello' + name
    //参数name就没有括号

作为参考

 var people = (name, age) => {
        const fullName = 'h' + name
        return fullName
    } 
    //如果缺少()或者{}就会报错

拓展的对象功能

对象初始化简写

ES5我们对于对象都是以键值对的形式书写,是有可能出现价值对重名的。例如:

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

键值对重名,ES6可以简写如下:

 function people(name, age) {
        return {
            name,
            age
        };
    }

ES6 同样改进了为对象字面量方法赋值的语法。ES5为对象添加方法:

  const people = {
        name: 'lux',
        getName: function() {
            console.log(this.name)
        }
    }

ES6通过省略冒号与 function 关键字,将这个语法变得更简洁

 const people = {
        name: 'lux',
        getName () {
            console.log(this.name)
        }
    }

ES6 对象提供了Object.assign()这个方法来实现浅复制。
Object.assign()可以把任意多个源对象自身可枚举的属性拷贝给目标对象,然后返回目标对象。第一参数即为目标对象。在实际项目中,我们为了不改变源对象。一般会把目标对象传为{ }

  const obj = Object.assign({}, objA, objB)

更方便的数据访问–解构

数组和对象是JS中最常用也是最重要表示形式。为了简化提取信息,ES6新增了解构,这是将一个数据结构分解为更小的部分的过程

ES5我们提取对象中的信息形式如下:

 const people = {
        name: 'lux',
        age: 20
    }
    const name = people.name
    const age = people.age
    console.log(name + ' --- ' + age)

是不是觉得很熟悉,没错,在ES6之前我们就是这样获取对象信息的,一个一个获取。现在,解构能让我们从对象或者数组里取出数据存为变量,例如

 //对象
    const people = {
        name: 'lux',
        age: 20
    }
    const { name, age } = people
    console.log(`${name} --- ${age}`)
    //数组
    const color = ['red', 'blue']
    const [first, second] = color
    console.log(first) //'red'
    console.log(second) //'blue'

Spread Operator 展开运算符

ES6中另外一个好玩的特性就是Spread Operator 也是三个点儿…接下来就展示一下它的用途。

组装对象或者数组

 //数组
    const color = ['red', 'yellow']
    const colorful = [...color, 'green', 'pink']
    console.log(colorful) //[red, yellow, green, pink]

    //对象
    const alp = { fist: 'a', second: 'b'}
    const alphabets = { ...alp, third: 'c' }
    console.log(alphabets) //{ "fist": "a", "second": "b", "third": "c"
}

有时候我们想获取数组或者对象除了前几项或者除了某几项的其他项

 //数组
    const number = [1,2,3,4,5]
    const [first, ...rest] = number
    console.log(rest) //2,3,4,5
    //对象
    const user = {
        username: 'lux',
        gender: 'female',
        age: 19,
        address: 'peking'
    }
    const { username, ...rest } = user
    console.log(rest) //{"address": "peking", "age": 19, "gender": "female"
}

对于 Object 而言,还可以用于组合成新的 Object 。(ES2017 stage-2 proposal) 当然如果有重复的属性名,右边覆盖左边

const first = {
        a: 1,
        b: 2,
        c: 6,
    }
    const second = {
        c: 3,
        d: 4
    }
    const total = { ...first, ...second }
    console.log(total) // { a: 1, b: 2, c: 3, d: 4 }

import 和 export

import导入模块、export导出模块

//全部导入
import people from './example'

//有一种特殊情况,即允许你将整个模块当作单一对象进行导入
//该模块的所有导出都会作为对象的属性存在
import * as example from "./example.js"
console.log(example.name)
console.log(example.age)
console.log(example.getName())

//导入部分
import {name, age} from './example'

// 导出默认, 有且只有一个默认
export default App

// 部分导出
export class App extend Component {};

以前有人问我,导入的时候有没有大括号的区别是什么。下面是我在工作中的总结:

  • 当用export default people导出时,就用 import people 导入(不带大括号)
  • 一个文件里,有且只能有一个export default。但可以有多个export。
  • 当用export name 时,就用import { name }导入(记得带上大括号)
  • 当一个文件里,既有一个export default people, 又有多个export name 或者 export age时,导入就用 import people, { name, age }
  • 当一个文件里出现n多个 export 导出很多模块,导入时除了一个一个导入,也可以用import * as example

Promise

在promise之前代码过多的回调或者嵌套,可读性差、耦合度高、扩展性低。通过Promise机制,扁平化的代码机构,大大提高了代码可读性;

用同步编程的方式来编写异步代码,保存线性的代码逻辑,极大的降低了代码耦合性而提高了程序的可扩展性。

说白了就是用同步的方式去写异步代码。

发起异步请求

   fetch('/api/todos')
      .then(res => res.json())
      .then(data => ({ data }))
      .catch(err => ({ err }));

今天看到一篇关于面试题的很有意思。

 setTimeout(function() {
      console.log(1)
    }, 0);
    new Promise(function executor(resolve) {
      console.log(2);
      for( var i=0 ; i<10000 ; i++ ) {
        i == 9999 && resolve();
      }
      console.log(3);
    }).then(function() {
      console.log(4);
    });
    console.log(5);

Generators

生成器( generator)是能返回一个迭代器的函数。生成器函数也是一种函数,最直观的表现就是比普通的function多了个星号*,在其函数体内可以使用yield关键字,有意思的是函数会在每个yield后暂停。

这里生活中有一个比较形象的例子。咱们到银行办理业务时候都得向大厅的机器取一张排队号。你拿到你的排队号,机器并不会自动为你再出下一张票。也就是说取票机“暂停”住了,直到下一个人再次唤起才会继续吐票。

OK。说说迭代器。当你调用一个generator时,它将返回一个迭代器对象。这个迭代器对象拥有一个叫做next的方法来帮助你重启generator函数并得到下一个值。next方法不仅返回值,它返回的对象具有两个属性:done和value。value是你获得的值,done用来表明你的generator是否已经停止提供值。继续用刚刚取票的例子,每张排队号就是这里的value,打印票的纸是否用完就这是这里的done。

// 生成器
    function *createIterator() {
        yield 1;
        yield 2;
        yield 3;
    }

    // 生成器能像正规函数那样被调用,但会返回一个迭代器
    let iterator = createIterator();

    console.log(iterator.next().value); // 1
    console.log(iterator.next().value); // 2
    console.log(iterator.next().value); // 3

那生成器和迭代器又有什么用处呢?

围绕着生成器的许多兴奋点都与异步编程直接相关。异步调用对于我们来说是很困难的事,我们的函数并不会等待异步调用完再执行,你可能会想到用回调函数,(当然还有其他方案比如Promise比如Async/await)。

生成器可以让我们的代码进行等待。就不用嵌套的回调函数。使用generator可以确保当异步调用在我们的generator函数运行一下行代码之前完成时暂停函数的执行。

那么问题来了,咱们也不能手动一直调用next()方法,你需要一个能够调用生成器并启动迭代器的方法。就像这样子的

 function run(taskDef) { //taskDef即一个生成器函数

        // 创建迭代器,让它在别处可用
        let task = taskDef();

        // 启动任务
        let result = task.next();

        // 递归使用函数来保持对 next() 的调用
        function step() {

            // 如果还有更多要做的
            if (!result.done) {
                result = task.next();
                step();
            }
        }

        // 开始处理过程
        step();

    }

生成器与迭代器最有趣、最令人激动的方面,或许就是可创建外观清晰的异步操作代码。你不必到处使用回调函数,而是可以建立貌似同步的代码,但实际上却使用 yield 来等待异步操作结束。

总结

ES6的特性远不止于此,但对于我们日常的开发开说。这已经是够够的了。还有很多有意思的方法。比如findIndex…等等。包括用set来完成面试题常客数组去重问题。我和我的小伙伴们都惊呆了!


  转载请注明: Tropical Cat Javascript基础语法

 上一篇
爱因斯坦的一百万年 爱因斯坦的一百万年
前言本篇短文具有很强的启发性,让人兴奋又联想翩翩,‘智能’、‘浩瀚宇宙’、‘时空’、‘未来’,这些都会激发人类心理的探索欲,让我们跟随作者的思维,发挥你的想象力,来一场穿越万年的时空旅行 1问题第一次被提出,是在2012年的计算机课堂上。人
2019-01-27
下一篇 
Hello World Hello World
Welcome to here!This is my first article. Some information about website:1、How was it made? (它是怎么来的?) 大约在2016年的夏天,我第一次接触
2019-01-24
  目录