七、JavaScript新特性

7.1、ECMAScript6新特性

7.1.1、关键字

1、let关键字

  • 不允许重复声明
  • 块儿级作用域
  • 不存在变量提升
  • 不影响作用域链

2、const关键字

  • 不允许重复声明
  • 块儿级作用域
  • 声明必须赋初始值
  • 值不允许修改

3、var关键字

  • 全局变量和函数局部变量
  • 没有块儿级作用域

4,三者区别

 

 7.1.2、解构赋值

 1、数组解构赋值

const arr = ["张学友", "刘德华", "黎明", "郭富城"];
let [zhang, liu, li, guo] = arr;
console.log(zhang);//张学友

2、对象解构赋值

const lin = {
    name: "林志颖",
    tags: ["车手", "歌手", "小旋风", "演员"]
};
let {name, tags} = lin;
console.log(name);//林志颖
console.log(tags);//["车手", "歌手", "小旋风", "演员"]

7.1.3、模板字符串

模板字符串(template string)是增强版的字符串,用反引号(`)标识

  • 字符串中可以出现换行符
  • 可以使用 ${xxx} 形式输出变量,变量拼接
//变量拼接
let name = '台湾同胞';
let result = `欢迎${name}回归祖国大陆`;
console.log(result);//欢迎台湾同胞回归祖国大陆

 7.1.4、简化对象写法

ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法

let person = {
    name:"张三",
    speak: function () {
    console.log(this.name);
}
};
person.speak();

7.1.5、箭头函数

const fnn=(num)=>{
  return num * 10;
}
console.log(fnn(20));
  • 如果形参只有一个,则小括号可以省略
  • 函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果
  • 箭头函数 this 指向声明时所在作用域下 this 的值,箭头函数不会更改 this 指向,用来指定回调函数会非常合适
  • 箭头函数不能作为构造函数实例化
  • 不能使用 arguments 实参
    //省略括号
    let fn = num => {
        return num * 10;
    };
    //省略花括号
    let fn = score => score * 20;
    

 7.1.6、rest 参数

 用于获取函数的实参,用来代替 arguments 参数,rest 参数非常适合不定个数参数函数的场景

function add(...a) {
  console.log(a);//(5) [1, 2, 3, 4, 5]
}
add(1, 2, 3, 4, 5);
// rest 参数必须是最后一个形参
function minus(a, b, ...args) {
    console.log(a, b, args);//100 1 (5) [2, 3, 4, 5, 19]
}
minus(100, 1, 2, 3, 4, 5, 19);

7.1.7、spread 扩展运算符

扩展运算符(spread)也是三个点(…),它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包

// 展开数组
let tfboys = ["德玛西亚之力", "德玛西亚之翼", "德玛西亚皇子"];
function fn() {
    console.log(arguments);//Arguments(3) ['德玛西亚之力', '德玛西亚之翼', '德玛西亚皇子']
}
fn(...tfboys);

7.1.8、Symbol

1、Symbol的使用

ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值,它是 JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型

  • Symbol 的值是唯一的,用来解决命名冲突的问题
  • Symbol 值不能与其它数据进行运算
  • Symbol 定义的对象属性不能使用 for…in 循环遍 历 ,但是可以使用 Reflect.ownKeys 来获取对象的所有键名

 2、Symbol内置值

 7.1.9、遍历器

const all = ["唐僧", "孙悟空", "猪八戒", "沙僧"];
//使用 for...of 遍历数组
for (let p of all) {
    console.log(p);
}

7.1.10、生成器

生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。* 的位置没有限制

  • 生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到 yield 语句后的值
  • yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next 方法,执行一段代码
  • next 方法可以传递实参,作为 yield 语句的返回值

 7.1.11、Promise

Promise 是 ES6 引入的异步编程的新解决方案,语法上 Promise 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果

1、Promise基本使用

//实例化 Promise 对象
const p = new Promise(function (resolve, reject) {
    setTimeout(function () {
        // 成功调用resolve()处理
        let data = "数据读取成功";
        resolve(data);
        // 失败调用reject()处理
        let err = "数据读取失败";
        reject(err);
    }, 1000);
});

//调用 promise 对象的 then 方法
p.then(function (value) {
    console.log(value);
}, function (reason) {
    console.error(reason);
});

2、 案例演示

const p = new Promise((resolve, reject) => {
    //1. 创建对象
    const xhr = new XMLHttpRequest();
    //2. 初始化
    xhr.open("GET", " https://v0.yiketianqi.com/api?unescape=1&version=v61&appid=94289351&appsecret=1PLuVHAI");
    //3. 发送
    xhr.send();
    //4. 绑定事件, 处理响应结果
    xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
            //判断响应状态码 200-299
            if (xhr.status >= 200 && xhr.status < 300) {
                //表示成功
                resolve(xhr.response);
            } else {
                //如果失败
                reject(xhr.status);
            }
        }
    }
});
//指定回调
p.then(function (value) {
  console.log("请求成功");
    console.log(value);
}, function (reason) {
    console.error(reason);
});

3、Promise-catch方法

const p = new Promise((resolve, reject) => {
    setTimeout(() => {
        //设置 p 对象的状态为失败, 并设置失败的值
        reject("出错啦!");
    }, 1000);
});

p.catch(function (reason) {
    console.error(reason);
});

7.1.12、Set

ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了 iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历

  • size:返回集合的元素个数
  • add():增加一个新元素,返回当前集合
  • delete():删除元素,返回 boolean 值
  • has():检测集合中是否包含某个元素,返回 boolean 值
  • clear():清空集合,返回 undefined
//创建一个空集合
let s = new Set();
//创建一个非空集合
let s1 = new Set([1, 2, 3, 1, 2, 3]);
//集合属性与方法
//返回集合的元素个数
console.log(s1.size);
//添加新元素
console.log(s1.add(4));
//删除元素
console.log(s1.delete(1));
//检测是否存在某个值
console.log(s1.has(2));
//清空集合
console.log(s1.clear());

 7.1.13、Map

ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是“键” 的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map 也实现了 iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历

  • size:返回 Map 的元素个数
  • set():增加一个新元素,返回当前 Map
  • get():返回键名对象的键值
  • has():检测 Map 中是否包含某个元素,返回 boolean 值
  • clear():清空集合,返回 undefined
//创建一个空 map
let m = new Map();
//创建一个非空 map
let m2 = new Map([
    ["name", "张三"],
    ["gender", "女"]
]);
//属性和方法
//获取映射元素的个数
console.log(m2.size);
//添加映射值
console.log(m2.set("age", 6));
//获取映射值
console.log(m2.get("age"));
//检测是否有该映射
console.log(m2.has("age"));
//清除
console.log(m2.clear());

7.1.14、class 类

ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过 class 关键字,可以定义类。基本上,ES6 的 class 可以看作只是 一个语法糖,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已

  • class:声明类
  • constructor:定义构造函数初始化
  • extends:继承父类
  • super:调用父级构造方法
  • static:定义静态方法和属性

//父类
class Phone {
    //构造方法
    constructor(brand, color, price) {
        this.brand = brand;
        this.color = color;
        this.price = price;
    }

    //对象方法
    call() {
        console.log("我可以打电话!!!")
    }
}

//子类
class SmartPhone extends Phone {
    constructor(brand, color, price, screen, pixel) {
        super(brand, color, price);
        this.screen = screen;
        this.pixel = pixel;
    }

    //子类方法
    photo() {
        console.log("我可以拍照!!");
    }

    playGame() {
        console.log("我可以玩游戏!!");
    }

    //方法重写
    call() {
        console.log("我可以进行视频通话!!");
    }

    //静态方法
    static run() {
        console.log("我可以运行程序")
    }

    static connect() {
        console.log("我可以建立连接")
    }
}

//实例化对象
const Nokia = new Phone("诺基亚", "灰色", 230);
const iPhone6s = new SmartPhone("苹果", "白色", 6088, "4.7inch", "500w");
//调用子类方法
iPhone6s.playGame();
//调用重写方法
iPhone6s.call();
//调用静态方法
SmartPhone.run();

 7.1.15、数值扩展

1、二进制、八进制、十进制和十六进制

let b = 0b1010//二进制
let o = 0o777;//八进制
let d = 100;//十进制
let x = 0xff;//十六进制
console.log(b);
console.log(o);
console.log(d);
console.log(x);

2、Number.EPSILON

Number.EPSILON:它是 JavaScript 表示的最小精度,EPSILON 属性的值接近于 2.2204460492503130808472633361816E-16

function equal(a, b) {
    if (Math.abs(a - b) < Number.EPSILON) {
        return true;
    } else {
        return false;
    }
}
console.log(0.1 + 0.2 === 0.3);
console.log(equal(0.1 + 0.2, 0.3));

3、Number.isFinite

Number.isFinite:检测一个数值是否为有限数

console.log(Number.isFinite(100));
console.log(Number.isFinite(100 / 0));
console.log(Number.isFinite(Infinity));
console.log(Number.isFinite(-Infinity));

4、Number.isNaN

Number.isNaN:检测一个数值是否为 NaN

console.log(Number.isNaN(123));

5、Number.parseInt

Number.parseInt:将一个字符串转换为整数

console.log(Number.parseInt("123abc"));

6、Number.parseFloat

Number.parseFloat:将一个字符串转换为浮点数

console.log(Number.parseFloat("3.1415926神奇"));

7、Number.isInteger

Number.isInteger:判断一个数是否为整数

console.log(Number.isInteger(5));
console.log(Number.isInteger(2.5));

8、Math.trunc

Math.trunc:将数字的小数部分抹掉

console.log(Math.trunc(3.5));

9、Math.sign

Math.sign:判断一个数到底为正数、负数、还是零

console.log(Math.sign(100));
console.log(Math.sign(0));
console.log(Math.sign(-20000));

7.1.16、对象扩展

  • Object.is:比较两个值是否严格相等,与『===』行为基本一致(+0 与 NaN)
  • Object.assign:对象的合并,将源对象的所有可枚举属性,复制到目标对象
  • __proto__、setPrototypeOf、 setPrototypeOf可以直接设置对象的原型

1、 Object.is

Object.is:判断两个值是否完全相等

console.log(Object.is(120, 120));// ===
console.log(Object.is(NaN, NaN));// ===
console.log(NaN === NaN);// ===

2、Object.assign

Object.assign:对象的合并,后边的对象会把前边对象的相同属性和方法覆盖,没有的属性和方法会合并

const config1 = {
    host: "localhost",
    port: 3306,
    name: "zhangsan",
    pass: "root",
    test1: "test1"
};
const config2 = {
    host: "127.0.0.1",
    port: 3309,
    name: "lisi",
    pass: "root",
    test2: "test2"
}
console.log(Object.assign(config1, config2));

3、设置原型对象

  • Object.setPrototypeOf:设置原型对象
  • Object.getPrototypeof:获取原型对象
const school = {
    name: "MySchool"
};
const cities = {
    xiaoqu: ["北京", "上海", "深圳"]
};
Object.setPrototypeOf(school, cities);
console.log(Object.getPrototypeOf(school));
console.log(school);

7.1.17、模块化

模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。

  • 防止命名冲突
  • 代码复用
  • 高维护性

 1、模块化的语法

模块功能主要由两个命令构成:export 和 import。

  • export 命令用于规定模块的对外接口
  • import 命令用于输入其它模块提供的功能

 2、模块化的暴露

//方式一:分别暴露
export let school = "华北理工大学";

export function study() {
    console.log("我们要学习!");
}
//方式二:统一暴露
let school = "华北理工大学";

function findJob() {
    console.log("我们要找工作!");
}

export {school, findJob};
//方式三:默认暴露
export default {
    school: "华北理工大学",
    change: function () {
        console.log("我们要改变自己!");
    }
}

3、模块化的导入

    // 引入 m1.js 模块内容
    import * as m1 from "./m1.js";
    // 引入 m2.js 模块内容
    import * as m2 from "./m2.js";
    // 引入 m3.js 模块内容
    import * as m3 from "./m3.js";
     
    m1.study();
    m2.findJob();
    m3.default.change();

4、解构赋值形式

   // 引入 m1.js 模块内容
    import {school, study} from "./m1.js";
    // 引入 m2.js 模块内容
    import {school as s, findJob} from "./m2.js";
    // 引入 m3.js 模块内容
    import {default as m3} from "./m3.js";

    console.log(school);
    study();

    console.log(s);
    findJob();

    console.log(m3);
    m3.change();

7.1.18、浅拷贝和深拷贝

如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝;如果B没变,那就是深拷贝,深拷贝与浅拷贝的概念只存在于引用数据类型。

1、浅拷贝

var obj1 = {
    name: "张三",
    age: 20,
    speak: function () {
        console.log("我是" + this.name);
    }
};

var obj2 = obj1;

// 当修改obj2的属性和方法的时候,obj1相应的属性和方法也会改变
obj2.name = "李四";
console.log(obj1);
console.log(obj2);

2、深拷贝

2.1、Array:slice()、concat()、Array.from()、… 操作符:只能实现一维数组的深拷贝

var arr1 = [1, 2, 3, 4];
var arr2 = arr1.slice();
arr2[0] = 200;
console.log(arr1);
console.log(arr2);

2.2、通用版

var obj1 = {
    name: "张三",
    age: 20,
    birthday: {
        year: 1997,
        month: 12,
        day: 5
    },
    speak: function () {
        console.log("我是" + this.name);
    }
};

var obj2 = deepClone(obj1);

// 当修改obj2的属性和方法的时候,obj1相应的属性和方法不会改变
obj2.name = "李四";
console.log(obj1);
console.log(obj2);

/**
 * 深拷贝通用方法
 * @param obj   需要拷贝的对象
 * @param has
 * @returns {any|RegExp|Date}
 */
function deepClone(obj, has = new WeakMap()) {
    // 类型检查
    if (obj == null) return obj;
    if (obj instanceof Date) return obj;
    if (obj instanceof RegExp) return obj;
    if (!(typeof obj == "object")) return obj;

    // 构造对象
    const newObj = new obj.constructor;

    // 防止自引用导致的死循环
    if (has.get(obj)) return has.get(obj);
    has.set(obj, newObj);

    // 循环遍历属性及方法
    for (let key in obj) {
        if (obj.hasOwnProperty(key)) {
            newObj[key] = deepClone(obj[key]);
        }
    }

    // 返回对象
    return newObj;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值