ES6 基础扫盲

发布于 2022-12-04 21:06:18 字数 12115 浏览 109 评论 0

为什么要学习 ES6?

SES6 可以说是一个泛指,指5.1版本以后的 JavaScript 的下一代标准,涵盖了 ES2015、ES2016、ES2017 等;亦指下一代 JavaScript 语言。现在主流的前端框架都采用ES6编写,所以学习ES6非常有必要.
学习参考网站

必看 阮一峰 ECMAScript 6 入门

本篇主要讲解 ES6 的知识点,内容如下:let和const、解构赋值、字符串操作、函数、数组API、集合、对象拷贝、延展操作符、对象补充、Generator、Proxy、Reflect。

一、let 和 const

ES6新增了let和const来声明变量,主要是解决var声明变量所造成的困扰和问题:

  • var不能用于定义常量
  • var可以重复声明变量
  • var存在变量提升
  • var不支持块级作用域

不可以重复声明变量

let sit = 'Geek-james';
let sit = 'james';
console.log(sit);

运行结果:

Identifier 'site' has already been declared

不存在变量提升

 console.log(site);
 let site = 'Geek-james';

运行结果:

site is not defined

可以定义常量

不能给常量重新赋值,但如果是引用类型的话可以进行修改。

// 自然对数的底
const E = 2.718;
E = 2.71;
console.log(E);

运行结果

Assignment to constant variable.

注意点:如果 const 定义一个对象,对象里面的键值对是可以被外界修改的。

coonst cv = {
    name:'james',
    intro:'I like it'
};
cv.name = 'zc520';
console.log(cv.name);

输出结果:

zc520

块级作用域

如果用var定义变量,变量是通过函数或者闭包拥有作用域;但,现在用let定义变量,不仅仅可以通过函数/闭包隔离,还可以通过块级作用域隔离。

块级作用域用一组大括号定义一个块,使用 let 定义的变量在大括号的外部是访问不到的,此外,let声明的变量不会污染全局作用域。

{
    let gk = 'Geek-like';
}
    console.log(gk);

运行结果:

site is not defined

案例运用

高级排他实现(不使用闭包)

window.addEventListener('load',function(){
    // 获取标签
    let allList = document.querySelectorAll('li');
    
    // 遍历
    let preIndex = 0;
    for (let i=0;i<allList.length;i++){
        allList[preIndex].className = '';
        this.className = 'current';
        preIndex = i;
    }
    
});

二、解构赋值

用于分解js中对象的结构。

用于数组的结构

//  普通写法
let nameArr = ['Geek', 'james', 'zc'];
let name1 = nameArr[0];
let name2 = nameArr[1];
let name3 = nameArr[2];

//  解构写法
let [name1, name2, name3] = nameArr;
console.log(name1, name2, name3);

对象的解构

//  写法1
let {name, age, sex} = {name: '小煤球', age: 1, sex: '公'};
// 结果: 小煤球 1 公
console.log(name, age, sex);

//  写法2: 解构重命名
let {name: lkName, age: lkAge, sex: lkSex} = {name: '小煤球', age: 1, sex: '公'};
// 结果: 小煤球 1 公
console.log(lkName, lkAge, lkSex);  

//  写法3: 可以设置默认值
let {name, age, sex = '公'} = {name: '小煤球', age: 1};
console.log(sex);  // 公

//  写法4:省略解构
let [, , sex] = ['小煤球', 1, '公 '];
console.log(sex);

应用场景

在封装 ajax 的 GET 和 POST 请求时,就可以运用到解构的知识点,代码如下:

// 普通写法
function ajax(option){
    let method = options.metod||"GET";
    let data = options.data || {};
    // ....
}

// 解构写法
function ajax({method = "GET",data}){
    console.log(method,data);
}
ajax({
    method:"POST",
    data:{"id":"111","name":"geek-james"}
});

三、延展操作符

延展数组

let arr1 = [ 'a', 'b', 'c'];
let arr2 = [1, 2, 3];
let result = [...arr1, ...arr2];
console.log(result); 
 //  [ "a", "b", "c", 1, 2, 3 ]

延展对象

let smallDog = {name:'james', age: 1};
let bigDog = {name: 'geek', age: 2};
let dog = {...smallDog, ...bigDog};
console.log(dog);  
// {name: "geek", age: 2}

注意: 如果对象中的属性一致,会被覆盖

开发应用场景

 function getMinValue() {
     console.log(Math.min(...arguments));
}
getMinValue(1, -99, 22, 10, 9);   //  -99

四、字符串操作

新增字符串方法

startsWith()

判断字符串是否以 XX 开头
let url = 'http://www.geekjames.com';
console.log(url.startsWith('http'));  // true

endsWith()

判断字符串是否以 XX 结尾
let file = 'index.html';
console.log(file.endsWith('html'));  // true

includes()

判断字符串中是否包含 XX
let str = 'geekjames';
console.log(str.includes('james')); // true

repeat()

//拷贝n份
let title = 'geek-james';
console.log(title.repeat(100));

padStart() / padEnd()

padStart() 用于头部补全,

padEnd() 用于尾部补全;

2.模板字符串

模板字符串用反引号 ` 包含,变量用 ${} 括起来,在开发中使用是非常灵活的。

let name = 'james';
let sex = '男';
let result = `我叫 ${name} , 我是 ${sex} 的`;

console.log(result); 
// 我叫james  , 我是 男 的

模板字符串遍历插入

let dArr = ['james','25'];
let as = dArr.map(function(value){
    return `<a href = "#">${value}</a>`
});
console.log(as);
let div = document.querySelector('#box');
div.innerHTML = as.join("");

函数操作

设置默认参数

function logPerson(name, sex = '男', age = 20) {
   console.log(name);
   console.log(sex);
    console.log(age);
}

//  undefined 男 20
logPerson();

延展参数转化

let logName = function (arg1, ...arg2) {
    console.log(arg1, arg2);
};

logName('宋小宝', '赵薇', '王菲', '那英');
// 宋小宝 , ["赵薇", "王菲", "那英"]

箭头函数

箭头函数简化了函数的的定义方式;
一般以 "=>" 操作符左边为输入的参数;
而右边则是进行的操作以及返回的值 inputs => output。

["赵薇", "王菲", "那英"].forEach(
       val => console.log(val)
);

注意:

  1. 多个参数要用 () 包起来,函数体有多条语句需要用 {} 包起来;
  2. 箭头函数根本没有自己的 this,所以内部的 this 就是外层代码块的 this。 正是因为它没有 this,从而避免了 this 指向的问题;
  3. 箭头函数中没有 arguments 对象。
let obj = {
    logThis:function(){
        //this 指向window
        setTimeout(function(){
            console.log(this);
        },1000);
        // this 指向obj
        setTimeout(()=>console.log(this),1000);
    }
}

注意

  • let 声明的变量不会放在 window 上
  • 对象不是作用域
let site = 'geek-James';
let obj = {
    site: 'james',
    func: () => {
        //  this指向window
        console.log(this);
        // undefined
        console.log(this.site);
    }
};

let func = obj.func;
func();

六、数组新增方法

ES6 中在原有数组的方法上又新增了一些好用的方法,比如:forEach、findIndex、find、map、reduce、filter、every、some等。

Array.from()

将一个数组或者类数组变成新数组,是浅拷贝操作。

let oldArr = [
     'james', 26, 
     {df1: '小Python',  df2: '土豆'}
];

let newArr = Array.from(oldArr);
console.log(newArr === oldArr); // false

Array.of()

创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。

// [8]
console.log(Array.of(8));

// [1, 2, 3]

console.log(Array.of(1, 2, 3));
// [ , , , , , , ]

console.log(Array(8));
// [1, 2, 3]

console.log(Array(1, 2, 3)); 

Array.fill()

用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。

语法结构:arr.fill(value[, start[, end]])

let array1 = [1, 2, 3, 4, 5];

// 用 撩 替换 索引[2,5]中的内容
console.log(array1.fill('james', 2, 5));

// 用 撩 替换 索引[1]中的内容
console.log(array1.fill('james', 1));

// 用 撩 替换 数组中所有内容
console.log(array1.fill('james'));

运行结果:

[1,2,'james','james','james']
[1,'james','james','james','james']
['james','james','james','james','james']

对象操作

属性简写

如果对象中属性值和变量名一样,并且属性的值就是变量表示值,则简写。

  • Object.is 对比两个值是否相等
  • Object.setPrototypeOf 将一个指定的对象的原型设置为另一个对象或者null
  • super 通过super可以调用prototype上的属性或方法。

对象拷贝-深拷贝和浅拷贝

浅拷贝 Object.assign

let obj1 = { dog1: { name: 'james' } };
let obj2 = { name: '小Python' };
let obj = {};
Object.assign(obj, obj1, obj2);
console.log(obj);
延展拷贝
let obj1 = { dog1: { name: 'james' } };
let obj2 = { name: '小Python' };
console.log({ ...obj1, ...obj2 });

深拷贝 JSON.parse和JSON.stringify

let obj1 = { dog1: { name: '小煤球' } };
let obj2 = { name: '小Python' };
console.log(JSON.parse(JSON.stringify({ ...obj1, ...obj2 })));

八、类操作

在之前定义类是通过构造函数来操作的,es6 新增了 class 关键字,此时,我们也可以像其它语言一样来创建各种类了。

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

    print(){
        console.log('我叫' + this.name + ',今年' + this.age + '岁');
    }
}

九、集合操作

set

一个Set是一堆东西的集合,Set有点像数组,不过跟数组不一样的是,Set里面不能有重复的内容;

// 创建一个集合
let set = new Set(['张三', '李四', '王五', '张三', '李四']);

console.log(set);
// 一个属性
console.log(set.size);


// 四个方法
// add
console.log(set.add('刘德华').add('旋之华'));
console.log(set);

// delete
console.log(set.delete('张三'));
console.log(set.delete('李四'));
console.log(set);

// has
console.log(set.has('张三'));
console.log(set.has('张三1'));

// clear
console.log(set.clear()); // undefined
console.log(set);

map

Map结构提供了“值—值”的对应,是一种更完善的Hash结构实现。如果你需要“键值对”的数据结构,Map比Object更合适。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。

实例属性和方法:size、set、get、has、delete、clear

// 创建一个Map
let obj1 = {a: 1}, obj2 = {b: 2};
const  map = new Map([
    ['name', '张三'],
    ['age', 18],
    ['sex', '男'],
    [obj1, '今天天气很好'],
    [obj2, '适合敲代码'],
    [[1,2], 'hhh']
]);

console.log(map);
console.log(map.size);

// set和get
map.set('friends', ['赵六', '力气']).set(['dog'], '小花');
console.log(map);
console.log(map.get('name'));
console.log(map.get(obj1));

// delete
map.delete(obj1);
console.log(map.delete('xxxx'));
console.log(map);

// has
console.log(map.has(obj1));
console.log(map.has(obj2));

// clear
map.clear();
console.log(map);

// 遍历
map.forEach(function (value, index) {
   console.log(index + ':' + value);
});

// 注意事项
map.set({}, '呵呵呵呵呵');
map.set({}, '哈哈哈哈');
console.log(map);
console.log({} === {});

十、Generator

为什么要使用 generator?开发中, 比如在做网络请求时我们会进行异步调用,为了保证调用顺序的正确性,通常我们会用回调函数,也可以采用Promise相关的技术来操作。还有一种常用的解决方案,它就是Generator生成器函数。

顾名思义,它是一个生成器,它也是一个状态机,内部拥有值及相关的状态,生成器返回一个迭代器Iterator对象,我们可以通过这个迭代器,手动地遍历相关的值、状态,保证正确的执行顺序。

声明

Generator 的声明方式类似一般的函数声明,只是多了个*号,并且一般可以在函数内看到yield关键字。

function* showNames() {
    yield '张三';
    yield '李四';
    return '王五';
}

let show = showNames();
 // {done: false, value: "张三"}

console.log(show.next());
// {done: false, value: "李四"}

console.log(show.next()); 
// {done: true, value: "王五"}

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

console.log(show.next()); 

迭代器有一个 next 方法,每次执行的时候会返回一个对象,对象里面有两个属性,一个是value表示返回的值,还有就是布尔值done,表示是否迭代完成。

十一、Proxy && Reflect

ES6 带来了 Proxy 和 Reflect,配合使用可以实现重载。Proxy 用于修改某些操作的默认行为,相当于对原始想进行的操作进行 包装,Reflect对象的方法与Proxy对象的方法一一对应,这使得Proxy对象可以方便的调用对应的Reflect方法完成默认行为。

function $set(obj,fn){
    let p = new Proxy(obj,{
        set(target,property,value,r){
            if(obj[value] !=value){
                console.log('----new ----');
                return Reflet.set(target,property,value,r)
            }
            return true;
        }
    });
    fn(p);
}

let obj = {name:'james',age:26,df:['haha','wangwang']};
$set(obj.df,function(arg){
    arg.push('阿黄');
    console.log(arg);
});

什么是重载?

简单说,就是函数或者方法有相同的名称,但是参数列表不相同的情形,这样的同名不同参数的函数或者方法之间,互相称之为重载函数或者方法。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

倦话

暂无简介

文章
评论
27 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文