ES6-01

 目录

1.ES6. 3

1.1ECMAScript发展历史: 3

1.2ES6简介... 3

2.关键字... 3

2.1 let关键字... 3

2.2 let与var比较... 4

2.2const关键字... 5

3.字符串拓展... 7

3.1多行字符串... 7

3.1.1单行字符串: 7

3.1.2多行字符串... 7

3.2原始字符串(String.raw)... 8

3.3重复字符串(repeat)... 9

3.4判断字符串位置... 9

4.数字拓展... 10

4.1 isNaN.. 10

4.2 isFinite. 11

4.3 isInteger. 12

5.数学对象拓展... 12

6.对象拓展... 12

6.1字面量(let obj = {}) 12

6.2 is【Object.is(  ,  )】... 13

6.3 assign(用于复制对象) 14

7.数组拓展... 15

7.1 from方法:【Array.from(arrLike, fn)】... 15

7.2 of方法:【Array.of()】... 16

7.3查找数组(find、findIndex) 16

7.4数组内部复制(arr.copyWithin(pos, start, end))... 17

7.5迭代器... 18

7.5.1迭代器方法... 18

7.5.2for of循环... 19

8. 解构... 21

8.1结构含义:(解析聚合数据的结构)... 21

8.2对象解构(let { key1, key2, ..keys} = obj)... 21

8.3数组解构(let [item1, item2, ..tems] = arr)... 23

8.4解构总结... 24

9.函数拓展... 24

9.1默认参数... 24

9.2获取剩余参数... 25

9.3箭头函数(let demo=(  )=>{  })... 26

1.ES6

1.1ECMAScript发展历史:

ES1.0 => 1997     ES2.0 => 1998

ES3.0 => 1999     S4.0 => 2007

ES3.1 => 2008     S5 => 2009

ES6 => 2015         ES2016(ES7) => 2016

ES2017 => 2017  ES2018 => 2018

由于ES每年新增的特性非常之多,所以开始以年为单位,定义其版本,从ES6开始,吸取了ES4失败的教训,没有强制浏览器实现这些语法,而是将这些语法编译成ES5 (ES3.1) 版本,这样浏览器就支持了。

所以,ES6受到各大浏览器厂商广泛的认可,并开始实现其语法,因此好的浏览器能够支持90%以上的语法了,所以很多语法可以直接用浏览器测试。

ES6 着眼于未来,是为企业级大型项目的开发而设计的。由于还有很多浏览

器. (IE6,7,8)没有实现ES6语法,所以我们要编译ES6,ES6支持面向对象编程方式(class, extends等关键字),但是又保留了弱类型语言,动态语言的特征。

1.2ES6简介

ECMA组织为了让制定的规范被编译成可被浏览器支持的版本,提供了babel编译库,ES每次发布版本,babel都会更新一个版本,在新版本中提供的功能,通过babel拓展来实现编译。

在nodejs端,在6.0版本之后,开始支持ES6,所以我们可以在后面的node学习中直接使用ES6了。

在浏览器端,为了兼容更多的浏览器。我们需要将ES6的代码,编译成浏览器支持的版本。

:当前的语法浏览器支持,因此可以用浏览器直接测试。

2.关键字

2.1 let关键字

用来定义块作用域变量

var定义函数级作用域变量的:

在函数内部定义的变量,外部无法访问,

在代码块(if, for)中定义的变量,外部可以访问

let定义块作用域变量的:

函数内部定义的变量,外部无法访问

在代码块(if, for)中定义的变量,外部仍然无法访问

用来定义块作用域变量的       

2.2 let与var比较

1.作用域

var函数级作用域                   let块级作用域

 // 块级作用域

        if (true) {var c = 30;let d = 40;

            // d 只能在代码块的内部访问

            console.log(d);  }//40

        console.log(c);//30

        // console.log(d);//let的外部无法访问

        //因此,var是函数级的,let 是块级的

2.重复定义

var可以重复定义变量           let不可以重复定义变量

      //重复定义

        var color = 'red';var color = 'green';

        console.log(color);//green;

        let color2 = 'red';let color2 = 'green';

        console.log(color2);//报错// has already been declared

3.声明前置

var支持声明前置                   let不支持声明前置

//声明前置

        console.log(ccc);//undefined//阔以访问,虽然无值

        var ccc = 'RED';

        let ccc = 'red';//报错//Cannot access 'ccc' before initialization

4.for循环中存储数据

var不能存储数据                   let可以存储数据

 //利用闭包存储数据  

for (var i = 0; i < 5; i++) {

            arr[i] = (function (i) {

                return function () {

                    console.log(i);} })(i) }//立即执行

        arr[3]()//3 // arr[2]();//2

//利用let存储数据

        for (let i = 0; i < 5; i++) { 

            arr[i] = function () {

                console.log(i);}}

arr[3]()//3

5.window挂载

var可以被挂载                       let不能被挂载

   // 被window挂载

        var e = 10;let f = 20;

        console.log(window.e);//10

        console.log(window.f);//undefined

2.2const关键字

const关键字是用于定义常量(一旦定义无法改变的变量,通常是表示一些固定不变的数据)

使用const关键字的特点:

1无法被修改

2支持块作用域

3无法重复定义

4无法声明前置

5不能被window挂载

6不能作为for循环体中的变量使用

7值只能是值类型如果是引用类型则可以被修改

工作中,通常是将用大写字母表示,并且横线分割单词,常用于定义配置量

在ES5中,我们可以通过冻结对象技术,或者设置writable:false特性,来模拟静态变量。但问题是:值如果是引用类型依然会被修改

在ES3.1中,我们可以通过单例模式来模拟静态变量。在方法中只定义取值方法,而不定义赋值方法即可

  //1.定义常量,不能修改

        // var a = 10;

        // a = 20;

        // console.log(a);//20//阔以被修改

        const a = 10;a = 20;

        console.log(a);//报错//Assignment to constant variable.



        //2.声明前置,不能前置,只能在后面访问

        console.log(COLOR);const COLOR = 'red';

        //报错//Cannot access 'COLOR' before initialization



        //3.不能重复定义

        const COLOR = 'red';

        const COLOR = 'asdas';//报错//'COLOR' has already been declared



        //4. 块级作用域

        function demo() {

            const COLOR = 'red';//支持函数级作用域

            // var COLOR = 'red'

            // let COLOR = 'red'

            console.log(111, COLOR) };//111 "red"//外部都无法访问

        demo();

        //块级

        if (true) {const COLOR = 'red';//支持块级作用域

            console.log(222, COLOR); }//222 "red"//外部无法访问

        console.log(COLOR); //外部都无法访问



        //5.不能挂载在window

        const COLOR = 'red';console.log(window.COLOR);//undefined



        //6.不能作为循环变量(常量不能被改变)

        for (const i = 0; i < 5; i++) {

            console.log(i);

        //第一次执行时,未被修改可以执行,第二次循环到i++时,修改了变量,报错

        }



        //7.值只能是值类型,不能是引用类型

        const OBJ = {width: 10,height: 20};

        OBJ.width = 111;OBJ.height = 2222;

        console.log(OBJ);//{width: 111, height: 2222}

        //会被修改,所以,不能使用引用类型



        //8.ES5模拟

        var obj = {color: 'red',num: 98,

            size: {//8.2

                width: 100,height: 200}}

        //8.1:设置特性

        Object.defineProperties(obj, {

            color: {writable: false},num: {writable: false},

            size: {writable: false},})

        obj.color = 'sdsd';obj.num = 678;

        obj.size = [1, 2, 3]//8.3没有修改size:{width: 123, height: 200}

        obj.size.width = 123; //8.2被修改了size:{width: 123, height: 200}

        //8.4即,size属性不能被修改,但是size的子属性可以被修改

        console.log(obj);//8.1没有被修改{color: "red", num: 98}



        //9.1:通过ES5中,对象的冻结实现

        Object.freeze(obj);

        obj.color = 'sdsd';obj.num = 678; //red //98

        obj.size = [1, 2, 3];//没有修改size

        obj.size.width = 123;//可以修改:{width: 123, height: 200}

      console.log(obj);//color: "red" num: 98 {width: 123, height: 200}

        //同8.4:即,size属性不能被修改,但是size的子属性可以被修改

//10.1在ES3.1中,使用单例模式

        var conf = (function () {

            var _data = {

                color: 'red',num: 98,

                size: {width: 100,height: 200}}

            //只返回取值器,不返回复制器

            return function (key) {return _data[key];}

        console.log(conf('color'));//red

        console.log(conf('num'));//98

        //如果返回的是对象可以被修改

        conf('size').width = 333333;

        console.log(conf('size'));//{width: 333333, height: 200}

3.字符串拓展

3.1多行字符串

3.1.1单行字符串:

一组单引号或者双引号定义的字符串

单行字符串的问题:

1单行字符串不能换行

2 一些特殊的按键要使用转义字符\n

3一些特殊的字符要使用转义字符\x20

4字符串标志符号不能直接嵌套

5单引号中不能直接写单引号,要转义\'

6双引号中不能直接写双引号,要转义\”

....

3.1.2多行字符串

ES6为了解决单行字符串中的问题,提供了多行字符串,

通过 ` 定义,在多行字符串中,只有`需要转义\,其他的字符,都可以直接书写

        var str = `hello

        qaq   " " ' '  \`

        `

        console.log(str);

并且ES6多行字符串支持插值语法:

 ${key}

${}提供了js环境,因此我们可以写js表达式

ES6的插值语法,让其它框架的插值语法的重要性,大打折扣。

    //数据

        let size = {width: 10,height: 20};

        // 输出:面积:10x20=200

        var str = '面积:' + size.width + 'x' + size.height + '=' + size.height * size.width

        //2.多行字符串

        var str = `面积:${size.width}x${size.height}=${size.width * size.height}`

        console.log(str);//面积:10x20=200

例二:

       //数据

        let data = [

{title: '1.被枚举到(for...in 或 Object.keys 方法),',type: '推荐'},

{title: '2.可以改变这些属性的值,也可以删除这些属性。',type: '关注'},

{title: '3.这个方法允许修改默认的额外选项(或配置)。',type: '热议'},

{title: '4.默认情况下,使用 Object.defineProperty()',type: '热点'},]

        //定义字符串

        let html = '';

        for (let i = 0; i < data.length; i++) { //遍历数据

            //字符串拼接

            html += `

            <li>

                <span>${data[i].title}</span>

                <span>${data[i].type}</span>

            </li>

            `}

          app.innerHTML = html;// console.log(html);

3.2原始字符串(String.raw)

在使用了转义字符之后,并且在浏览器查看的时候,我们只能看到结果不能看到原始完整的字符串(包含转义字符),于是ES6中拓展了String.raw方法。

用于,查看完整的原始字符串。

使用方式:

String.raw``

1.参数通过多行字符串的形式传递

2.字符串中的转义字符串不会被转义

//转义字符

        let str = `hello \nqa\nq`;//被转义了,即换行了

        //原始字符串

        // let str = String.raw`hello \nqa\nq`//hello \nqa\nq

        console.log(str);

        //实现://不让\n实现,把\n改成\\n即可

        //注意\\n是一个整体,匹配修改时,要一起匹配

        console.log(str.replace(/\n/g, '\\n'));//hello \nqa\nq

3.3重复字符串(repeat)

ES6中拓展了repeat方法用于重复输出字符串

参数:要重复的次数

返回值:重复的结果

注意:不影响原始字符串

        let str = `hello ||`; // 重复字符串(repeat)

        //让str重复三次

        console.log(str.repeat(3));//hello ||hello ||hello ||

        console.log(str.repeat(0));//

        console.log(str);//hello ||

        //实现:

        String.prototype.qaqRepeat = function (num) {

            var result = ''; //this 代表字符串//定义结果字符串

            //循环拼接

            for (var i = 0; i < num; i++) {result += this;}

            return result}

        console.log(str.qaqRepeat(3));//hello ||hello ||hello ||

3.4判断字符串位置

startsWith(str, pos)

是否以参数字符串开头

截取后面的部分,并且包含截取位置字符

str:参数字符串 (子字符串)             pos:字符串截取位置

返回值:布尔值

  //定义字符串

        //        0 1 2 3 4 5 6

        let str = `我是一个大帅逼`

 console.log(str.startsWith('我', 0));//true

        console.log(str.startsWith('帅逼', 5));//true

endsWith(str, pos)

是否以参数字符串结尾

截取前面的部分,并且不包含截取位置字符

 console.log(str.endsWith('帅逼'));//true

        console.log(str.endsWith('帅', 5));//false

        console.log(str.endsWith('帅', 6));//true

includes(str, pos)

是否包含参数字符串

截取后面的部分,并且包含截取位置字符

    console.log(333, str.includes('帅'));//true

        console.log(333, str.includes('帅逼', 5));//true

4.数字拓展

ES6中为数字拓展了几个方法:

 isNaN(数字?) isFinite(有限?) isInteger(整数?)

        var num1 = 0 / 1;//      0

        var num2 = 0 / - 1;//   -0

        var num3 = 1 / 0;//     Infinity

        var num4 = - 1 / 0;//   -Infinity

        var num5 = 0 / 0;//     NaN

4.1 isNaN

1.全局中的NaN

全局中有一个isNaN方法,是用于判断是否是NaN(not a Number)

全局中isNaN在判断的时候,会进行类型转换

       console.log(isNaN(num4));       //F

        console.log(isNaN(num5));       //T

        console.log(isNaN(100.00));     //F

        console.log(isNaN('100abc'));   //T

        console.log("+'100abc'", isNaN(+'100abc'));  //F//T//存疑

        //用typeof查看+'100abc 时,貌似会会在后台进行数字的 转换

        console.log(isNaN(parseInt('100abc')));  //F

// isNaN('123ABC');

// 👆true:  parseInt("123ABC")的结果是 123, 但是Number("123ABC")结果是 NaN

        console.log(isNaN(Math.floor('100abc'))); //F//T

        //Math方法不支持隐性转换,100abc仍是字符串 不是一个数字

        console.log(isNaN(1 / 3)); //F

        console.log(isNaN(Math.PI)); //F

2.Number拓展的isNaN

在判断的时候不会做类型转换

1.先必须是数字

其次才去判断是否是NaN

2.如果NaN,则返回true

如果不是NaN,则返回false

        console.log(Number.isNaN(num4));                   //F

        console.log(Number.isNaN(num5));                   //T

        console.log(Number.isNaN(100.00));                 //F

        console.log(Number.isNaN('100abc'));//T//先直接判断类型:字符串//F

console.log(Number.isNaN(+'100abc'));//T//是数字类型,但不是一个数字//是NaN

        console.log(Number.isNaN(parseInt('100abc')));     //F

        console.log(Number.isNaN(Math.floor('100abc')));   //T

        console.log(Number.isNaN(1 / 3));                  //F

        console.log(Number.isNaN(Math.PI));                //F

4.2 isFinite

全局中:

有一个isFinite方法, 是用于判断是否是有限的

全局中的isFinite,在判断的时候,会进行类型转换

Number拓展的isFinite

在判断的时候不会做类型转换

1.首先必须是数字

其次才去判断是否是有限的

2.如果是有限的,则返回true

如果不是有限的,则返回false

注意:

       1. 判断数学上是不是有限的

       2. 只要是整数都是有限的

 console.log(Number.isFinite(num4));                   // T //F

        console.log(Number.isFinite(num5));                   // F

        console.log(Number.isFinite(100.00));                 // F //T

        console.log(Number.isFinite('100.00'));               // F

        console.log(Number.isFinite('100abc'));               // F

        console.log(Number.isFinite(+'100abc'));              // F

        console.log(Number.isFinite(parseInt('100abc')));     // F //T

        console.log(Number.isFinite(Math.floor('100abc')));   // F

        console.log(Number.isFinite(1 / 3));                  // F //T

        console.log(Number.isFinite(Math.PI));                // F //T

4.3 isInteger

Number拓展的isInteger方法,用于判断是否是整型的

在判断的过程中,会校验类型

1.首先必须是数字

其次才去判断是否是整型的

2.如果是整型,则返回true

如果不是整型,则返回false

5.数学对象拓展

就是Math对象的拓展

ES6为了适应大型项目,解决自身运算的问题,拓展了大量的方法。

Math.cbrt:计算一个数的立方根

Math.fround:返回一个数的单精度浮点数形式。

Math.hypot:返回所有参数的平方和的平方根

Math.expm1(x):返回ex- 1。

Math.log1p(x):返回1 + x的自然对数。如果x小于-1,返回NaN。

Math.log10(x):返回以10为底的x的对数。如果x小于0,则返回NaN。

Math.log2(x):返回以2为底的x的对数。如果x小于0,则返回NaN。

三角函数方法:

Math.sinh(x)返回x的双曲正弦(hyperbolic sine)

Math.cosh(x)返回x的双曲余弦(hyperbolic cosine)

Math.tanh(x)返回x的双曲正切(hyperbolic tangent)

Math.asinh(x)返回x的反双曲正弦(inverse hyperbolic sine)

Math.acosh(x)返回x的反双曲余弦(inverse hyperbolic cosine)

Math.atanh(x)返回x的反双曲正切(inverse hyperbolic tangent)

Math.sign返回一个数字的标志,用来判断数字范围的

(0, Infinity] =>1,[-Infinity, 0) => -1,0=>0,-0 => -0,NaN =>NaN

6.对象拓展

6.1字面量(let obj = {})

对象字面量: letobj = {}

省略语法:

1如果定义的属性名称属性值变量同名,我们可以省略属性名称以及冒号

2可以对属性名称书写表达式,通过[]动态的设置属性名称,之前可以通过[]获取属性,现在我们可以通过[]设置属性名

3在对象中定义的方法可以省略冒号以及function关键字

         let color = "red";

        let obj = {//定义对象

            // color: color//1.1添加一个color属性

            //1.2如果定义的属性名称与属性值变量同名,可以省略属性名称以及冒号

            color,

            //1.4对象字面量中,可以通过[]来动态的设置属性名称

            [color]: 200,

            //1.5 [ ]提供了js环境,可以书写复杂的表达式

            [color.toLocaleUpperCase() + 'hello']: 200,

            //1.6获取方法

            // getColor: function () {  //老式写法

            //     return this.color; }

          //ES6中,属性方法可以省略冒号以及function关键字

            getColor() {return this.color;}};

        //设置属性

        // obj[color] = 100;//1.3{color: "red", red: 100}

        console.log(obj);

        //1.1&1.2{color: "red"}

        //1.4{color: "red", red: 200}

        //1.5{color: "red", red: 200, REDhello: 200}

        //1.6{color: "red", red: 200, REDhello: 200, getColor: ƒ}

        console.log(obj.getColor());//1.6//red

6.2 is【Object.is(  ,  )】

is方法用于判断两个参数是否全等(===)

全等判断有几个问题:

1:0和 -0之前在进行全等判断的时候,得到的是true

0和- 0之间是差了一个符号位在二进制中,存储的数据是不同的

2:NaNNaN在进行全等判断的时候,得到的是false

3:所有NaN都表示“不是一个数字”,它们存储的地址是一样

对象拓展的is方法:

在判断0-0的时候得到的false

在判断NaN的时候得到的就是true

注意:

       比较的是存储的地址。

         console.log(0 / 1 === 0 / -1);         //true

        console.log(NaN === +'asd');           //false

        //is方法纠正上述 === 的错误//除此之外,is方法与 === 是一致的

        console.log(Object.is(0 / 1, 0 / -1)); //false

        console.log(Object.is(NaN, +'asd'));   //true

6.3 assign(用于复制对象)

ES6拓展的assign是用于复制对象的,和jQuery、undescore中的extend方法类似

使用方式: Object.assign(obj, obj1, obj2)

obj:被复制的目标对象

第二个参数开始,都是复制的对象

返回值:目标对象obj

注意:

1.后面对象中的同名属性会覆盖前面对象中的属性

2.assign方法实现的是一个浅复制

浅复制:

值类型是直接复制,而引用类型是改变指向,没有真正的复制

深复制:

值类型是直接复制,引用类型也是直接复制,并不是改变指向(函数除外)

3.简单实现深复制: JSON.parse(JSON.stringify), 但是转换json字符串的时候,会过滤掉函数

4.jQuery中的extend方法,第一个参数传递 true的时候就是深复制

 //实现(浅复制)(这是静态方法,直接放在Object上面)

        Object.qaqAssign = function (target) {

            //遍历后面的参数对象

            for (var i = 1; i < arguments.length; i++) {

                //获取当前参数对象

                var obj = arguments[i];

                //将obj中的属性赋值给target

                for (var key in obj) {

                    target[key] = obj[key];   //赋值

                }

            }

            //返回目标对象

            return target}

        var result = Object.qaqAssign(obj1, obj2, obj3);

7.数组拓展

7.1 from方法:【Array.from(arrLike, fn)】

from方法是用于遍历类数组对象,或将类数组对象转换成数组,是数组的静态方法。

类数组对象:

1.可以通过索引值获取属性值,并且要具备length属性的这一类对象

2.类数组对象不能使用数组的遍历器方法,ES6中拓展的from方法可以将类数组对象转为真正的数组,之后就可以使用数组的常用方法

使用方式:

Array.from(arrLike, fn)

arrLike:类数组对象

fn:执行的函数

参数:            成员值、索引值

作用域:   全局作用域(即this默认指向window)

如果传递的fn参数,此时,fn方法的返回值是from函数的执行结果

总结:

from方法不仅可以将类数组转为数组,还可以遍历类数组对象

    <div>1-1-1</div>

    <div>2-2-2</div>

    <div>3-3-3</div>

    <div>4-4-4</div>

    <div>5-5-5</div>

 //将类数组对象转成数组

        //1.可以将类数组转为数组;2.还可以遍历类数组对象

        let arr = Array.from(div, function (item, index) {

            console.log(111, arguments);

            //3.返回值影响from方法运行的结果

            return index});

        console.log(arr);//(5) [div, div, div, div, div]

        arr.forEach(function () {

            console.log(arguments);})

//实现

        Array.qaqFrom = function (arrLike, fn) {

            //1.定义返回的数组

            let result = [];

            //2.遍历类数组对象

            for (var i = 0, len = arrLike.length; i < len; i++) {

                //2.1判断是否传递fn

                if (fn) {

                    //2.2传递了fn,存储fn执行结果

                    result.push(fn(arrLike[i], [i]))

                } else {

                    //2.3没有传递fn,直接存储fn的成员

                    result.push(arrLike[i], [i])}}

            return result;}

        //使用

        var arr = Array.qaqFrom(div, function (item, index) {

            item.innerHTML = 'qaq' + index;

            return item;});

        console.log(arr);

7.2 of方法:【Array.of()】

of方法用于创建数组的,是数组的一个静态方法

之前通过new Array(或者是Array()创建数组有一些问题:

  1如果没有传递参数,得到的是一个空数组

  2如果传递了一个数字参数,得到的是带有一个长度的空数组

  3如果传递一个非数字参数,得到的是带有一个成员的数组

  4如果传递了多个参数,得到就是一个带有多个参数的数组

ES6中拓展的of方法可以实现:将所有传递的参数都作为数组中的成员存在

创建数组的四种方式

字面量[],

构造函数new Array(),

工厂方法Array(),

Array.of()

 //实现数组的静态方法,

        Array.qaqOf = function () {

            // console.log(arguments);

            // return Array.from(arguments)//一:ES6方法

            //二:普通方法:slice方法可以转换数组

            return Array.prototype.slice.call(arguments)}

        let arr1 = Array.qaqOf();         //[]

        let arr2 = Array.qaqOf(5);        //[5]

        let arr3 = Array.qaqOf('5');      //["5"]

        let arr4 = Array.qaqOf(5, 6, 7);  //[5, 6, 7]

        console.log(arr1, arr2, arr3, arr4);

7.3查找数组(find、findIndex)

在ES5中拓展了查找成员的方法: indexOf lastIndexOf

在ES6中拓展了查找成员的方式: find findIndex

1.允许参数是可以执行的函数

2.参数:执行的函数

函数中有三个参数:成员值、索引值、原数组

3.作用域:全局作用域(即this默认指向window

4.find方法

在查找成员的时候,如果找到了则返回该成员,如果没有找到则返回undefined

5.findIndex方法

在查找成员的时候,如果找到了则返回该成员的索引值,如果没有找到返回-1,在查找的过程中,一旦找到则停止遍历

7.4数组内部复制(arr.copyWithin(pos, start, end))

ES6为了实现数组内部复制成员提供了一个方法: copyWithin

1.使用方式:

arr.copyWithin(pos, start, end)

pos:  要粘贴的位置

start: 要复制的起始位置(包含起始位置)

end:  要复制的结束位置(不包含结束位置)

返回值:原数组,并且原数组发生变化

例如:

[0,1,2,3,4,5, 6,7,8,9]. copyWithin(3, 6, 9)

结果:

[0,1,2,6,7,8,6,7,8,9]

             //实现

        Array.prototype.qaqCopyWithin = function (pos, start, end) {

            //截取

            var arr = this.slice(start, end);

            // for (var i = 0; i < arr.length; i++) {//法一:粘贴

            //     //更新成员,返回原数组

            //     this[i + pos] = arr[i];

            // }



            //法二:数组操作

            // (splice() 方法用于添加或删除数组中的元素。)

            // array.splice(index,howmany,item1,.....,itemX)

            // this.splice(pos, end - start)

            // this.slice.apply()将数组作为参数传递

            this.slice.apply(this, [pos, end - start].concat(arr))

            //返回原数组

            return this;}

        //缩成一句话

        Array.prototype.qaqCopyWithin = function (pos, start, end) {

return this.slice.apply(this, [pos, end - start].concat(this.slice(start, end))), this;}

        //逗号语法,前面的执行完后,执行后面的,并把后面的作为return返回

        var result = arr.qaqCopyWithin(2, 5, 8);

        console.log(result);//[0, 1, 5, 6, 7, 5, 6, 7, 8, 9]

        console.log(result === arr);//true//修改的是原数组

7.5迭代器

7.5.1迭代器方法

ES6中为了遍历数组中成员,拓展了三个迭代器方法:

keysvaluesentries

keys:获取索引值

values:获取成员值

entries:获取索引值以及成员值: [index, item, ]

由于实现了数组的迭代器接口方法,就可以使用for of或者是next方法遍历

实现了迭代器接口的数据,都有next方法,可以通过next方法来遍历成员

返回值:一个对象

value:表示成员值

done:表示是否遍历完成

如果遍历完成了,此时: done将永远是true

value将永远是undefined

var arr = ['red', 'green', 'blue', 'pink'];

        // //创建迭代器//索引值

        // var result1 = arr.keys();

        // console.log(result1);



        //还可以通过for of循环遍历

        var result1 = arr.values();

        for (let item of result1) {

            console.log(item);

}

        //遍历每一个成员

        console.log(result1.next());//{value: 0, done: false}

        console.log(result1.next());//{value: 1, done: false}

        console.log(result1.next());//{value: 2, done: false}

        console.log(result1.next());//{value: 3, done: false}

        console.log(result1.next());//{value: undefined, done: true}

        console.log(result1.next());//{value: undefined, done: true}



        //创建迭代器//成员值

        var result2 = arr.values();

        console.log(result2);

        //遍历每一个成员

        console.log(result2.next());//{value: red, done: false}

        console.log(result2.next());//{value: green, done: false}

        console.log(result2.next());//{value: blue, done: false}

        console.log(result2.next());//{value: pink, done: false}

        console.log(result2.next());//{value: undefined, done: true}

        console.log(result2.next());//{value: undefined, done: true}



        //创建迭代器//成员值

        var result3 = arr.entries();

        console.log(result3);

        //遍历每一个成员

        console.log(result3.next());//{value: Array(2), done: false}//value: (2) [0, "red"]

        console.log(result3.next());//

        console.log(result3.next());//

        console.log(result3.next());//

        console.log(result3.next());//



//一旦遍历完成,需要重新创建一个迭代器,var result4=.......

7.5.2for of循环

1.for of循环是ES6专门为实现了迭代器接口的对象设计的循环结构

for of是专门为迭代器接口设置的遍历方法

2.语法:

for (let item of data) {}

可以像其它循环一样在内部使用continue break等关键字

3.for of也是可以遍历数组的,但是在遍历过程中无法使用索引值

遍历数组的时候,item表示数组的每一个成员,没有办法访问索引值,但是我们可以在外部定义一个循环变量,在循环体中手动更新。

for of循环遍历数组的时候,不需要通过索引值访问成员,而for循环以及for in循环要通过索引值访问

4.for in也可以遍历数组,但是有一些问题:

遍历的时候,key显示的是字符串,不是数字(改变了索引值类型)

5.总结:

for循环用于遍历数组、类数组对象

for in循环用于遍历对象

for of循环遍历实现了迭代器接口的对象(包括数组)

        var arr = ['red', 'green', 'blue', 'pink'];

        //创建迭代器//索引值

        var result1 = arr.values();

        //for循环与 for in循环无法遍历

        // for (var i = 0; i < result1.length; i++) {

        //     console.log(result1);//没有报错,但是也没有执行

        // }

        for (let key in result1) {

            console.log(key);  }//没有报错,但是也没有执行



        //循环//遍历对象

        for (let item of result1) {

            // //遍历到蓝色就停止

            // if (item === 'blue') {

            //     break;

            // }

            // //遍历到蓝色就跳过蓝色

            // if (item === 'blue') {

            //     continue;

            // }

            console.log(item);}

        //迭代器对象一旦遍历完成,就无法再遍历了

        for (let ltem of result1) {

console.log(222); }//前面迭代器执行过result1之后,就不会再执行这个循环了

        

        //遍历数组

        for (let item of arr) {console.log(item);}

        for (let item of arr) {console.log(222, arr);}

        //数组可以多次遍历



        // for of也是可以遍历数组的,但是在遍历过程中,无法使用索引值

        var index = 0;

        for (var item of arr) {

            console.log(item, index);

            //与while循环类式,需要手动更新循环变量

            index++;}

8. 解构

8.1结构含义:(解析聚合数据的结构)

1.所谓解构就是解析聚合数据的结构

2.在ES5中的聚合数据有:

对象、数组

在之前,对象中获取数据的方式

只能通过点语法或中括号语法

在之前,数组中获取数据的方式

只能通过中括号语法

3.在ES6中简化了获取数据的方式,提供了解构语法:对象解构与数组解构

4.解构语法不会影响原来的数据

8.2对象解构(let { key1, key2, ..keys} = obj)

1.语法:

let { key1, key2, ..keys} = obj; 

key1相当于obj.key1

key2相当于obj.key2

keys获取的是剩余的属性,如果没有剩余的属性,获取到的就是一个空对象

注意:

解构出来的属性、变量一定是和对象中的属性同名

         var obj = {

            num: 100,color: 'red',shuaibi: 'it is me',

            arr: [1, 2, 3],

            size: {width: 222,height: 555},

            demo() {

                console.log(222, this); }};//指向调用者:obj

        //过去访问数据 的方法:通过访问obj获取数据

        // console.log(obj.num);//100

        // console.log(obj['color']);//red



        //ES6对象解构语法: let { key1, key2, ..keys} = obj;

        //其中: ...keys三点语法获取剩余的属性

        // let { num, color, ...qaq } = obj;

        console.log(num);//100

        console.log(color);//red

        console.log(qaq);//{}//没有剩余的对象就为:空对象

        //{shuaibi: "it is me", arr: Array(3), size: {…}, demo: ƒ}

        obj.demo()

2.解构问题:

1如果使用var解构,会污染全局对象(window),我们可以使用let关键字解决

//使用var会污染全局对象,一般使用let

        var { num, color, ...qaq } = obj;

        console.log(window.num);//100

        //结构语法相当于在全局 var num = obj.num;//var 换成let即可

2解构出来的方法,方法中的this将发生变化

        obj.demo();//指向调用者:obj

        //结构出来,this指向会发生改变

        let { num, color, demo, ...qaq } = obj;

        demo();

        //指向为window//因为相当于let demo= obj.demo,window也调用了demo

        //Window {window: Window, self: Window, document: document, name: "", location: Location, …}

        //注意:严格模式指向undefined

3对于引用类型来说,只是指向的改变,而对于值类型来说,是真正的复制

  //结构值类型的是复制,结构引用类型的是指向改变(引用同一个)

        let { num, color, demo, arr, size, ...qaq } = obj;

        //修改数据

        num = 200; arr[1] = 112233; size.width = 123;

        console.log(num);//200

        console.log(arr);//[1, 112233, 3]

        console.log(size);//{width: 123, height: 555}

        console.log(obj);

        /** arr: (3) [1, 112233, 3] //引用类型 :指向同一个存储地址

         * color: "red"           //值类型:是直接复制一份,改变前后互不影响

         * demo: ƒ demo()

         * num: 100

         * shuaibi: "it is me"

         * size: {width: 123, height: 555}**/

3.逆运用:

我们可以通过三个点语法,将一个对象中的所有数据传递给一个对象字面量中: { ...keys }

 // 结构语法的:逆运用:

        let { num, color, demo, ...qaq } = obj;

        // 注意:num和color是对象字面量的省略语法

        //      (对象与属性名同名[参./ES06-01/04.1],...qaq是解构的逆运用)//记住等号是赋值的意思即可

        var newObj = { num, ...qaq };

        console.log(newObj);

        //{num: 100, shuaibi: "it is me", arr: Array(3), size: {…}}

        //注意:由于解构出来的数据会创建全局变量,因此,工作中常配合模块化开发使用(相当于局部变量)

8.3数组解构(let [item1, item2, ..tems] = arr)

1.语法:

let [item1, item2, ...items] = arr;

item1表示第一个成员

item2表示第二个成员

items表示剩余的成员

注意:

1.如果使用var解构,也会污染全局对象(window) ,我们可以通过使用let关键字解决

2.左边数组与数据有对应的成员,返回成员;没有的话,返回undefined

       var arr = ['red', 'green', 'blue', 'pink',

                  'orange', 'gold', 'yellow', 'purple', 'gray'];

        // console.log(arr.slice(2));//获取第三个及其后面的成员

        //结构语法//let [item1, item2, ..tems] = arr

        //注意:var 同样会污染window,使用let即可

        //等价方式: let red = arr[0];

        let [red, green, ...items] = arr;

        console.log(red, green);//red green

        console.log(items);// ["blue", "pink", "orange", "gold", "yellow", "purple", "gray"]

2.获取剩余成员的语法:

1如果数组有剩余的成员,获取到的是数组中所有的剩余成员

2如果没有剩余的成员,获取到的是一个空数组

3前面解构的变量,可以正常使用

3.逆运:

我们可以通过三个点语法,将一个数组中的所有数据传递到一个数组字面量中[ ...r](复制数组)

        //解构

        let [red, green, ...items] = arr;

        //复制数组

        // var newArr = [red, green, ...items];

        var newArr = [red, ...items, green];//注意,新数组里面的顺序,是按复制的顺序排列

        console.log(newArr);//["red", "green"......]全部都复制了过来

 //如果只传递 ...items,newArr与arr成员完全相同,但不相等

        var newArr = [...items];

        console.log(newArr == arr);//false

        console.log(newArr === arr);//false

8.4解构总结

1.记住单个等号赋值的意思即可:

解构指的是等号左侧的部分,

逆运用是等号右侧的部分,

例如,复制数据

2.解构:

对象解构,属性名称匹配

数组解构,索引值匹配(位置对应)

9.函数拓展

9.1默认参数

之前适配默认参数的方式:

1可以通过 || 运算符来适配参数的默认值

但是使用 || 运算符会忽略6个值为false的参数:

 0 ‘ ’ undefined null false NaN

2可以使用三元运算符:  

?  :   

如果参数过多,书写比较麻烦

3使用extend | assign方法适配对象, 对于值类型的参数不适用

4 在ES6为了解决这样的问题,提供了适配默认参数的方式,直接在参数集合中为形参赋值即可

如果传递了参数,则使用传递的参数

如果没有传递参数,则使用默认参数

注:ES6拓展的适配默认参数的方式与三元运算符的方式是等价的

        //定义函数

        //4.1在ES6中,可以直接为参数赋值,定义默认参数

        function demo(color = 'pink') {

            //1.1通过 ||(或)运算符设置默认值

            // color = color || 'red';

            //2.1三元运算符适配,如果参数较多会比较麻烦

            // color = color === undefined ? 'red' : color;

            //3.使用extend | assign方法适配对象, 对于值类型的参数不适用。且是比较麻烦的

            console.log(color);

        }

        //执行函数并传递参数

        demo();         //1.2 red   //2.1 red   //4.1 pink

        demo(0);        //1.2 red   //2.1  0    //4.1  0

        demo(NaN);      //1.2 red   //2.1 NaN   //4.1 NaN

        demo(false);    //1.2 red   //2.1 false //4.1 false

        demo(null);     //1.2 red   //2.1 null  //4.1 null

        demo(undefined);//1.2 red   //2.1 red   //4.1 pink

        demo('red');    //1.2 red   //2.1 red   //4.1 red

9.2获取剩余参数

之前,可以通过arguments来获取所有参数,但是arguments是一个类数组对象,不能使用数组的常用方法。

于是ES6拓展了获取剩余参数语法获取的剩余参数是一个数组,所以可以直接使用数组的常用方法

1.语法:

function demo(arg1, arg2, ...args) {}

arg1表示第一个参数

arg2表示第二个参数

args表示剩余的参数

        // function demo() {

     // console.log(arguments); }//1.1类数组,不能直接使用数组方法

// 获取剩余参数

    // function demo(num1, num2, ...args) {

//console.log(num1, num2, ...args); }//2.1获取的是数组,可以使用数组方法

         demo();              //1.2:[]       //2.2:undefined undefined

        demo(1);             //1.2:[1]         //2.2:1 undefined

        demo(1, 2);          //1.2:[1,2]       //2.2:1 2

        demo(1, 2, 3);       //1.2:[1,2,3]     //2.2:1 2 3

        demo(1, 2, 3, 4);    //1.2:[1,2,3,4]   //2.2:1 2 3 4

        demo(1, 2, 3, 4, 5); //1.2:[1,2,3,4,5] //2.2:1 2 3 4 5

//3.1求参数和老方法

        function add() {

            // 根据argument求和

            var result = 0;

            for (var i = 0; i < arguments.length; i++) {

                result += arguments[i]}

            return result}

        console.log(add(1, 2, 3, 4, 5)); //3.2测试//15

        //3.3获取剩余参数 求和

        function add(...nums) {//通过数组的方法求和

            return nums.reduce(function (res, item) {

                return res + item}, 0)}

        console.log(add(1, 2, 3, 4, 5));//15

2.获取剩余参数的语法:

1如果有剩余的参数,获取到的是一个由所有剩余参数组成的数组

2如果没有剩余的参数,获取到的是一个空数组

3前面参数可以正常使用,如果没有对应的参数,返回undefined

4在箭头函数中有广泛的应用

3.获取剩余参数的逆运用:

语法:

demo(...args)

1.我们可以将一个数组中成员作为参数传递到一个方法中

2.在之前我们可以通过apply方法,将数组中的每一项数据传递到一个方法中

3.但是使用apply需要考虑this的指向问题

4.我们可以使用获取剩余参数的语法,就不需要考虑this指向的问题了,正常执行函数。

  //4.1逆运用

        var arr = [1, 2, 3, 4, 5];

        function add(...nums) {

            //通过数组的方法求和

            return nums.reduce(function (res, item) {

                return res + item

            }, 0)

}

        // //4.2使用apply传递

        // var result = add.apply(null, arr);

        //4.3使用 ...args传递

        let result = add(...arr)

        console.log(result);//4.2/4.3: 15

9.3箭头函数(let demo=(  )=>{  })

1.在ES5中定义函数的方式:

 1函数定义式、 2函数表达式、 3构造函数式

4.在ES6中又拓展了一种方式:

箭头函数

2.语法:

let demo=(  )=>{  }

(  ) :  表示参数集合

=> :  是箭头函数的标志

{  } :  是函数体

3.几点省略语法:

1如果参数集合中只有一个参数,即可省略参数集合

如果使用三个点语法获取剩余参数或者解构语法不能省略参数集合

2如果函数中只有一句话,或者只有返回值的时候,可以省略return以及函数体

        // 4.1省略参数集合

        let print = (msg) => {

            console.log(msg);}

        //4.3只有一个参数省略参数集合

        let print = msg => {

            console.log(msg);}

        print('hello');//4.2/4.3 hello

        //4.4获取剩余参数语法不能省略

        let print = (...args) => {

            console.log(...args); }//三个点语法的逆运用

        print(100, 'hello', true);//4.5 100 "hello" true

        //4.6解构语法不能省略

        let print = ({ msg }) => {

            console.log(msg);}

        print({ color: 'red', msg: 'hello' })//hello



        //4.7省略函数体

        var arr = [1, 3, 5, 7, 9];

        //数组映射

        // let result = arr.map((item) => {

        //     // return item * item

        //     // return Math.pow(item, 2)

        //     return Math.pow(item, 3)

        // })

        //4.8进行省略

        // let result = arr.map(item => item * item)

        let result = arr.map(item => Math.pow(item, 2))

        console.log(result);//[1, 9, 25, 49, 81]

4. 箭头函数的特点:

1无法使用arguments,但是我们可以使用三个点语法获取剩余参数

        // // 1.1无法使用arguments

        // let add = (...args) => {//1.3添加...args

        //     // console.log(args);//1.2//1.3

        //     return args.reduce((res, item) => res + item)//1.5

        // }

        // console.log(add(1, 2, 3, 4, 5));

        //1.2报错arguments不能使用  

 //1.3 [1, 2, 3]   //1.5 15

        //1.6简化

        let add = (...args) => args.reduce((res, item) => res + item)

        console.log(add(1, 2, 3, 4, 5));//1.6 15

2无法作为构造函数来使用

 // 2.1无法作为构造函数来使用

        // function Player(x, y) {

        //     this.x = x;

        //     this.y = y;}

        // //2.7函数表达式

        // let Player = function (x, y) {

        //     this.x = x;

        //     this.y = y; }

        //2.8箭头函数不允许

        let Player = (x, y) => {

            this.x = x;

            this.y = y;}

        // //2.2定义原型方法//老方法

        // Player.prototype={

        //     constructor: }//这个需要重写

        // Player.prototype.getPosition = function () { };//2.3

        //2.4

        Object.assign(Player.prototype, {

            getPosition() {

                console.log(this.x, this.y);}})

        //2.5实例化

        let p = new Player(100, 200);

        p.getPosition()

        //2.6/2.7 100 200

        //2.8 报错:箭头函数不能作为构造函数

3箭头函数中的this指向永远是定义时

       A在普通函数中,this是执行时的上下文对象,谁调用指向谁

B无论使用call、apply或者是 bind方法都无法改变箭头函数的this指向

C改变箭头函数this指向唯一的方式就是改变其宿主环境this

也就是说改变其外部函数的作用域

         //3.1箭头函数中的this指向永远是 定义时的

        //3.2严格模式:中的普通函数 this是undefined

        'use strict'

        console.log(this);//window

        var demo = () => {

            console.log(this);

        };

        //3.3普通函数

        function demo2() {

            console.log(this);

        }

        demo()//3.1 Window

        demo2()//3.3 undefined

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值