欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

前端笔记之ES678&Webpack&Babel(中)对象|字符串|数组的扩展&函数新特性&类

程序员文章站 2022-03-24 17:59:44
一、对象的扩展 1.1对象属性名表达式 ES6可以在JSON中使用[]包裹一个key的名字。此时这个key将用表达式作为属性名(被当做变量求值),这个key值必须是字符串。 1.2 Object.assign()方法 该方法用于对象的合并,将源对象的所有可枚举的属性,复制到目标对象。 Object. ......

一、对象的扩展

1.1对象属性名表达式

es6可以在json中使用[]包裹一个key的名字。此时这个key将用表达式作为属性名(被当做变量求值),这个key值必须是字符串。

var a = 'name'
var obj = {
    [a] : "小明",
    age:12,
    sex:"男"
}
console.log(obj.name)

前端笔记之ES678&Webpack&Babel(中)对象|字符串|数组的扩展&函数新特性&类


 

1.2 object.assign()方法

该方法用于对象的合并,将源对象的所有可枚举的属性,复制到目标对象。

object.assign()方法的第一个参数是目标对象,后面的参数都是源对象。

let obj1 = {a:1};
let obj2 = {a:2, b:3};
let obj3 = {b:4, c:5};
object.assign(obj1,obj2,obj3)

console.log(obj1)
console.log(obj2)
console.log(obj3)

前端笔记之ES678&Webpack&Babel(中)对象|字符串|数组的扩展&函数新特性&类

 

注意:

l 它没有返回值,会直接改变object.assign()中的第一个参数对象

l 后面可以罗列无限个对象,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性

如果该参数不是对象,则会先转成对象,然后返回。

typeof object.assign(2) // "object"

 

由于undefinednull无法转成对象,所以如果它们作为参数,就会报错。

object.assign(undefined) // 报错
object.assign(null) // 报错

1.3 object.keys()方法

它可以将一个对象所有的键名(key)转为一个数组对象,并返回:

let o = {a: 1, b: 2, c: 3};
console.log(object.keys(o)); //[ 'a', 'b', 'c' ]

前端笔记之ES678&Webpack&Babel(中)对象|字符串|数组的扩展&函数新特性&类


1.4 object.values()方法

它可以将一个对象所有的键值(value)转为一个数组对象,并返回:

let o = {a: 10, b: 20, c: 33};
console.log(object.values(o)); //[ 10, 20, 33 ]

前端笔记之ES678&Webpack&Babel(中)对象|字符串|数组的扩展&函数新特性&类


1.5 object.entries()方法

它可以将一个对象所有的键名(key)和键值(value)转为一个数组对象,并返回:

let o = {a: 10, b: 20, c: 33};
console.log(object.entries(o)); 

前端笔记之ES678&Webpack&Babel(中)对象|字符串|数组的扩展&函数新特性&类


1.6 object.is()

es5 比较两个值是否相等,只有两个运算符:相等运算符(==)和严格相等运算符(===。它们都有缺点,前者会自动转换数据类型,后者的nan不等于自身,以及+0等于-0javascript 缺乏一种运算,在所有环境中,只要两个值是一样的,它们就应该相等。

 

es6 提出“same-value equality”(同值相等)算法,用来解决这个问题。object.is就是部署这个算法的新方法。它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。

console.log(object.is('a','a')); //true
console.log(object.is({}, {}));  //false
console.log(object.is([], []));  //false

不同之处只有两个:一是:+0不等于-0,二是nan等于自身。
console.log(+0 === -0); //true
console.log(nan === nan); //false

console.log(object.is(+0, -0)); //false
console.log(object.is(nan, nan)); //true

 

二、字符串的扩展

2.1定义字符串``反引号

之前定义字符串,必须使用以下定界符

""或''

 

它们的缺点是在做连字符串的时候,不方便:

var name = "小明";
var age = 12;
var str = "你好,我是" + name + "我今年" + age + "岁";
console.log(str)

 

es6中用``来做定界符:

var str = `你好`;
console.log(str)
console.log`str`
console.log(typeof str)

前端笔记之ES678&Webpack&Babel(中)对象|字符串|数组的扩展&函数新特性&类

var name = "小明";
var age = 12;
var str = `你好,我是${name}我今年${age}岁`;
console.log(str)

注意:只有``中能够用${}嵌套变量

 

动态求值:

var str = `今年是${2016 + 2}`;
console.log(str); //2018

能写简单运算、函数调用、变量、math函数、数组表达式方法(mapreducefilterjoin)、三元运算符

 

function sum(a,b){
    return a + b;
}

var str1 = `哈${math.random()}哈`;
var str2 = `哈${sum(3,4)}哈`;
var str3 = `哈${5 > 10 ? true : false}哈`;
console.log(str1)
console.log(str2)
console.log(str3)

前端笔记之ES678&Webpack&Babel(中)对象|字符串|数组的扩展&函数新特性&类


2.2字符串方法

以前javascript只有indexof方法,可以用来确定一个字符串是否包含在另一个字符串中。

 

es6又提供了三种新方法:

includes()   返回boolean值,检查字符串或数组中是否存在某项

startswith() 返回boolean值,检查参数字符串是否在原字符串的开头

endswith() 返回boolean值,检查参数字符串是否在原字符串的结尾

 

var url = "http://www.aiqianduan.com/";
console.log(url.includes("www"));    //true
console.log(url.startswith("http")); //true
console.log(url.endswith("com/"));   //true

 

这三个方法都支持第二个参数,表示开始搜索的位置:

let s = 'hello world!';
console.log(s.includes('hello', 6))   //false
console.log(s.startswith('world', 6)) //true
console.log(s.endswith('hello', 5))   //true

上面代码表示,使用第二个参数n时,endswith的行为与其他两个方法有所不同。它针对前n个字符,而其他两个方法针对从第n个位置直到字符串结束。

 

 repeat()返回一个新的字符串能够将原字符串重复n

console.log('★'.repeat(10))

前端笔记之ES678&Webpack&Babel(中)对象|字符串|数组的扩展&函数新特性&类


三、数组的扩展

3.1 findfindindex方法

数组实例的find方法,用于找出第一个符合条件的数组成员,它不会遍历完整的数组。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该成员,就结束。如果没有符合条件的成员,则返回undefined

let arr = [2,3,4,5,6,7,8,9,10,11,12];
let item = arr.find(function(item){
    return item > 7;
})
console.log(item)

 

数组的findindex()方法的用法和find一样,返回第一个符合条件的数组成员的下标位置,如果所有的成员都不符合,则返回-1

let arr = [2,3,4,5,6,7,8,9,10,11,12];

let index = arr.findindex(function(item){
    return item > 7;
})
console.log(index); //6

 


3.2 array.from()方法

使用...”可以类数组对象变为真正的数组。

什么是类数组对象?就是对象的键名都是01234...,并且有length属性,可以被枚举。

var obj = {
    0 : 100,
    1 : 200,
    2 : 300,
    length:3
}
var arr= array.from(obj);
console.log(obj)
console.log(arr)

 

前端笔记之ES678&Webpack&Babel(中)对象|字符串|数组的扩展&函数新特性&类

 

最常见的类数组对象是arguments

function fun(){
    console.log([...arguments]);
}
fun(1,2,3,4)

前端笔记之ES678&Webpack&Babel(中)对象|字符串|数组的扩展&函数新特性&类


3.3 array.of()方法

它可以将零散的值变为数组

let arr = array.of(3,4,5,6,7,8);
console.log(arr)

前端笔记之ES678&Webpack&Babel(中)对象|字符串|数组的扩展&函数新特性&类


3.4 includes()方法

验证数组中是否存在某一项:

let arr = [3,4,5,88,100];
console.log(arr.includes(88));  //true
console.log(arr.includes(888)); //false

该方法的第二个参数表示搜索的起始位置,默认为0。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度

(比如第二个参数为-4,但数组长度为3),则会重置为从0开始。

[1, 2, 3].includes(3, 3);  // false
[1, 2, 3].includes(3, -1); // true

没有该方法之前,我们通常使用数组的indexof方法,检查是否包含某个值。

 

indexof方法有两个缺点,一是不够语义化,它的含义是找到参数值的第一个出现位置,所以要去比较是否不等于-1,表达起来不够直观。二是,它内部使用严格相等运算符(===)进行判断,这会导致对nan的误判。

[nan].indexof(nan)
// -1

 

includes使用的是不一样的判断算法,就没有这个问题。

[nan].includes(nan)
// true

3.5 fill()数组填充

var arr = new array(10).fill("★");
console.log(arr)

前端笔记之ES678&Webpack&Babel(中)对象|字符串|数组的扩展&函数新特性&类


3.6 for of遍历

增加了一种数组的遍历方法,叫for of遍历,通常配合arr.entries()

var arr = ['白板','幺鸡','二条','三饼','四筒'];
for(var v of arr){
    console.log(v)
}

前端笔记之ES678&Webpack&Babel(中)对象|字符串|数组的扩展&函数新特性&类

var arr = ['白板','幺鸡','二条','三饼','四筒'];
for(var [k,v] of arr.entries()){
    console.log(k,v)
}

前端笔记之ES678&Webpack&Babel(中)对象|字符串|数组的扩展&函数新特性&类


四、es6中函数的新特性

4.1箭头函数(重点)

es6 允许使用箭头=>)定义函数

注意:

l => 是一个完整的运算符,不能拆开 = > 

箭头函数一定是匿名函数,要使用=”赋值接收某一个匿名的箭头函数,来给这个匿名的箭头函数命名。

 

函数的扩展:

function的基本简化

const sum = function(a, b){
    return a + b;
}

 

等价于,现在用箭头函数的定义:

const sum = (a, b)=>{
    return a + b;
}

 

return{}()都可以简化

const sum = (a,b)=> a + b;
console.log(sum(4,5))

如果箭头函数中,只有一条return语句时,可以简化“{}”和return

言外之意:如果语句不止一条,必须加{}”和return语句

 

如果箭头函数形参变量中,只有一个参数,可以不写形参变量的()”圆括号

const mianji = r => 3.14 * r * r
console.log(mianji(10))

 

如果箭头函数不需要参数就使用一个圆括号代表参数部分。

const f = ()=> 5
// 等价于
const f = function(){
    return 5;
}

 

由于{}”被解析为函数体,所以如果箭头函数直接返回一个对象,必须在对象外加上圆括号,否则报错。

// const fun = (id,name)=> {"id": id, "name": name} //报错
const fun = (id,name)=> ({"id": id, "name": name})

console.log(fun(10001,"小明"))

 

可以连续写箭头函数,表示函数的嵌套,外层的函数返回了一个函数。

const fun = a=> b=> a + b;
console.log(fun(10)(5))

 

等价于下面两种写法:

const fun = (a)=>{
    return (b)=>{
        return a + b;
    }
}
function fun(a){
    return function(b){
        return a + b;
    }
}

注意:箭头函数有几个使用注意点。

1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。

3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。

4)不可以使用yield命令,因此箭头函数不能用作 generator 函数。

上面四点中,第一点尤其值得注意。this对象的指向是可变的,但是在箭头函数中,它是固定的。


4.2函数的剩余参数

es6 引入 rest 参数(形式为...变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。

箭头函数和普通函数一样,也可以使用es6的默认参数和剩余参数:

const fun = (a,...b)=>{
    console.log(a)
    console.log(b)
}
fun(1,2,3,4,5,6);

前端笔记之ES678&Webpack&Babel(中)对象|字符串|数组的扩展&函数新特性&类


4.3函数的默认参数

es6允许为函数的参数设置默认值,即直接写在参数定义的后面:

const sum = (a, b=10)=>{
    return a + b;
}
console.log(sum(3,4)); //7
console.log(sum(3)); //13

在函数的形参中赋值了默认值10,表示如果调用的时候没有传入b的值,默认值才会生效。


4.4箭头函数的上下文

以前说的判断上下文
规则1:直接圆括号调用fn(),此时this是window 规则2:对象打点调用obj.fn(),此时this是obj 规则3:数组中枚举函数调用arr[3](),此时this是arr 规则4:定时器调用函数setinterval(fn , 10),此时this是window 规则5:按钮的事件监听obtn.onclick = fn,此时this是obtn 规则6:call和allpay可以指定,fn.call(obj),此时this是obj 规则7:用new调用函数,new fn(),此时this是秘密新创建的空白对象。 上面的规则,不适用于箭头函数!

箭头函数的上下文是什么规则呢?

箭头函数的上下文,是这个函数定义时所处的上下文,而不是看如何调用的。

箭头函数定义时所在的函数内的this是谁,这个箭头函数的this终身是谁,不能被改变。

 

 题目1:应用场景,之前定时器经常要进行备份,现在有箭头函数就不需要备份了:

var obj = {
    a : 10,
    fn: function(){
        setinterval(()=>{
            console.log(this.a)
        },1000)
    }
}

obj.fn()

红色这个函数的上下文是obj,此时箭头函数的上下文就继承自obj对象,而不是window

 

题目2fun函数里面有一个箭头函数,并且箭头函数执行了

function fun(){
    const fn = ()=>{
        console.log(this.a)
    }
    fn();
}
var laowang = {
    a : 666,
    fun : fun
}
laowang.fun();

因为fun函数是laowang打点调用的,所以fun函数的上下文是laowang,此时箭头函数的上下文就是laowang

因为箭头函数的上下文,是箭头函数定义时,所在函数的上下文。

 

相等于在外部备份了一次this

function fun(){
    var self = this;
    const fn = function(){
        console.log(self.a)
    }
    fn();
}
var laowang = {
    a : 666,
    fun : fun
}
laowang.fun();

 

题目3

var obj = {
    say : function(){
        var f1 = ()=>{
            console.log(this); //obj
            settimeout(()=>{
                console.log(this); //obj
            })
        }
        f1();
    }
}

obj.say();

因为f1定义是所处的函数中的this指向objsettimeout的箭头函数this继承自f1,所以不管有多少层嵌套都是obj

 

题目3的延伸:

var obj = {
    say : function(){
        var f1 = function(){
            console.log(this); //window
            settimeout(()=>{
                console.log(this); //window
            })
        }
        f1();
    }
}

obj.say();

结果:window,因为箭头函数在定义的时候它所处的环境相当于window,所以在箭头函数内部的this就是windownode环境没有window,可以在浏览器执行)

也就是说,箭头函数的上下文取决于如何被定义,而不是如何被调用,正好和之前普通function相反。

进一步说,箭头函数上下文不能被改变。

 

题目4

function fun(){
    const fn = ()=>{
        console.log(this.a)
    }
    const xiaohua = {
        a : 9999999
    }

    fn.call(xiaohua); //call和apply都不能改变箭头函数的上下文
}
var laowang = {
    a : 666,
    fun : fun
}
laowang.fun();

输出还是laowanga,就是666,箭头函数上下文终身不能改。

箭头函数不能被callapply

 function还没有下岗

如果需要一个可变的上下文函数,用function

如果需要一个自动备份外部上下文的函数,用箭头函数


 

4.5 bind()绑定上下文

只有function能被bind(),箭头函数不能被bind()

一个函数如果被bind()指向了某个对象,此时这个函数上下文将终身绑定到这个对象,永不改变,callapply都没有改变。

注意:bind()只绑定上下文,但不会执行函数,和callapply不太一样 

function fun(){
    console.log(this.a);
}

var laowang = {
    a : 666
}

var xiaozhang = {
    a : 8888
}

fun = fun.bind(laowang);  //fun函数的上下文终身在是laowang
fun();                        //即使圆括号调用fun函数,也是laowang

fun.call(xiaozhang);        //call和apply也不能改变,还是laowang
fun.apply(xiaozhang);
fun = fun.bind(xiaozhang); //再次bind也无效,还是laowang
setinterval(fun,1000);      //定时器也不能改变它

只要写一遍bind(),没有任何方法可以改变函数的this指向。


 

4.6双冒号运算符

箭头函数可以绑定this对象,大大减少了显式绑定this对象的写法(callapplybind)。但是,箭头函数并不适用于所有场合,所以现在有一个提案,提出了函数绑定function bind)运算符,用来取代callapplybind调用。

函数绑定运算符是并排的两个冒号(::),双冒号左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即this对象),绑定到右边的函数上面。 

foo::bar;
// 等同于
bar.bind(foo);

foo::bar(...arguments);
// 等同于
bar.apply(foo, arguments);

4.7对象中函数的简化

 

var result = object.keys(obj).map(item=>({
    "label": item,
    "children" : obj[zimu].map(pinpai=>({
        "label" : pinpai.brand ,
        "children": pinpai.series.map(chexi=>({
            "label" : chexi
        }))
    }))
}));

 

 

 

var obj = {
    a : 100,
    fun : function(){
        console.log(this.a);
    }
}

 等价于:

var obj = {
    a : 100,
    fun(){
        console.log(this.a);
    }
}
obj.fun();

 

不等于:

var obj = {
    a : 100,
    fun:()=>{
        console.log(this.a);
    }
}
obj.fun();

4.8 babel翻译它们

翻译前

翻译后

前端笔记之ES678&Webpack&Babel(中)对象|字符串|数组的扩展&函数新特性&类

 

前端笔记之ES678&Webpack&Babel(中)对象|字符串|数组的扩展&函数新特性&类

 

 

箭头函数就是自动备份了this

练习:下面有一个对象,不改变原来的对象,创建新的obj2对象,将id2那个车主的地区变为“中国”。

var obj1 = {
    "nowshow": 8,
    "nowtype":"all",
    "dataarr":[
        {
            "id":1,
            "brand":"奔驰",
            "price":50,
            "saler":{
                "name":"王尼玛",
                "provice":"德国"
            }
        },
        {
            "id":2,
            "brand":"宝马",
            "price":20,
            "saler":{
                "name":"李全蛋",
                "provice":"韩国"
            }
        }
    ]
};
var obj2 = {
    ...obj1,
    "dataarr":obj1.dataarr.map((item)=>{
        if(item.id == 2){
            return {
                ...item,
                saler:{
                    ...item.saler,
                    provice:"中国"
                }
            }
        }

        return item;
    })
}
console.log(json.stringify(obj2))

五、类(构造函数)

5.1 es6类的新写法

原来定义一个类,是用构造函数,用new调用。

function people(name,age,sex){
    this.name = name;
    this.age = age;
    this.sex = sex;
}
people.prototype.sayhello = function(){
    console.log(`我是${this.name}`);
}
people.prototype.singsing = function(){
    console.log(`${this.name}在唱歌`);
}

var xiaoming = new people("小明",12,"男");
var xiaohong = new people("小红",12,"女");
xiaoming.sayhello();
xiaohong.sayhello();

 

es6中引入新的关键字class用来定义类,所有类的属性都要写在constructor()构造函数中,所有类的方法要一个个罗列在class花括号中。

class people {
    constructor(name,age,sex){
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    sayhello(){
        console.log(`我是${this.name}`);
    }

    sing(){
        console.log(`${this.name}在唱歌`);
    }
}

var xiaoming = new people("小明",12,"男");
var xiaohong = new people("小红",12,"女");
xiaoming.sayhello();
xiaohong.sing();

 

虽然写在有了class关键字,可以更优雅的定义类,但原理没有任何变化。

程序中没有出现prototype,但方法还是在它身上。


 

5.2 es6继承新写法

//人类
function people(name,age,sex){
    this.name = name;
    this.age = age;
    this.sex = sex;
}

people.prototype.sayhello = function(){
    console.log(`我是${this.name}`);
}

//学生类
function student(name,age,sex,xuehao,banji){
    // this.name = name;
    // this.age = age;
    // this.sex = sex;
    people.apply(this, arguments); //继承人类的属性
    this.xuehao = xuehao;
    this.banji = banji;
}

//下面一条语句即可继承people类,改变prototype的指向
student.prototype = new people();

student.prototype.kaoshi = function(){
    console.log(`${this.name},改打游戏啦,别学习了`);
}

var xiaoming = new student("小明",12,"男",10001, 08);
xiaoming.sayhello();
xiaoming.kaoshi();

 

es6引入了新的关键字extends,表示继承

在子类的构造函数中,必须写super()调用超类(父类)的构造函数。

//学生类
class people {
    //构造函数
    constructor(name,age,sex){
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
    sayhello(){
        console.log(`我是${this.name}`);
    }
    sing(){
        console.log(`${this.name}在唱歌`);
    }
}


//学生类
class student extends people{
    //构造函数
    constructor(name,age,sex,xuehao,banji){
        super(name,age,sex)
        this.xuehao = xuehao;
        this.banji = banji;
    }

    kaoshi(){
        console.log(`我是${this.name},在考试`);
    }
}

var xiaoming = new student("小明",12,"男",10001, 08);
xiaoming.sayhello();
xiaoming.kaoshi();

babel如何翻译class

babel会将class的写法翻译为原来的functionprototype的写法。


 

var result = object.keys(obj).map(item=>({

    "label": item,

    "children" : obj[zimu].map(pinpai=>({

        "label" : pinpai.brand ,

        "children": pinpai.series.map(chexi=>({

            "label" : chexi

        }))

    }))

}));