d

doris

V1

2022/07/28阅读:19主题:红绯

ECMASript 5/6 笔记

ES5

ES5 除了正常运行模式(又称为混杂模式),还添加了第二种运行模式:"严格模式",就是使 JavaScript 在更严格的语法条件下运行。

  • 在全局或函数的第一条语句定义为: 'use strict'

  • 如果浏览器不支持,只解析为一条简单的语句, 没有任何副作用

    // 全局使用严格模式
    'use strict';
    girl = '迪丽热巴';

    // 函数中使用严格模式
    function main(){
     'use strict';
     boy = '吴亦凡';
    }
    main();

语法和行为改变

  • 必须用 var 声明变量,不允许使用未声明的变量
  • 禁止自定义的函数中的 this 指向 window
  • 创建 eval 作用域
  • 对象不能有重名的属性(Chrome 已经修复了这个 Bug,IE 还会出现)
  • 函数不能有重复的形参
  • 新增一些保留字, 如: implements interface private protected public

Object 扩展方法

Object.create(prototype, [descriptors]) 方法可以以指定对象为原型创建新的对象,同时可以为新的对象设置属性, 并对属性进行描述

//创建一个汽车的对象
var car = {
    name : '汽车',
    runfunction(){
        console.log('我可以行驶!!');
    }
};

//以 car 为原型对象创建新对象
var aodi = Object.create(car, {
    brand: {
        value'奥迪',
        writablefalse,         //是否可修改
        configurablefalse,     //是否可以删除
        enumerabletrue         //是否可以使用 for...in 遍历
    },
    color: {
        value : '黑色',
        wriablefalse,
        configurablefalse,
        enumerabletrue
    }
});

Object.defineProperties(object, descriptors) 方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。

// 定义对象
var star = {
    firstName'刘',
    lastName : '德华'
};

// 为 star 定义额外的属性
Object.defineProperties(star, {
    fullName: {
        getfunction(){
            return this.firstName + this.lastName;
        },
        setfunction(name){
            var res = name.split('-');
            this.firstName = res[0];
            this.lastName = res[1];
        }
    }
});

// 修改 fullName 属性值
star.fullName = '张-学友';

// 打印属性
console.log(star.fullName);

call、apply 和 bind

  • call 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数
  • apply 方法调用一个具有给定 this 值的函数,以及作为一个数组(或类似数组对象)提供的参数
  • bind 同 call 相似,不过该方法会返回一个新的函数,而不会立即执行

ECMASript 6

ECMAScript 是由Ecma国际通过ECMA-262标准化的脚本程序设计语言。TC39(Technical Committee 39)是推进 ECMAScript 发展的委员会,在维护ECMA-262。

let关键字!

let关键字用来声明变量,使用let声明的变量有几个特点:

  1. 不允许重复声明

  2. 块儿级作用域

  3. 不存在变量提升

以后声明变量使用let就对了

const关键字!

const 关键字用来声明常量

const声明有以下特点:

  1. 声明一定要赋初始值(名称大写)

  2. 不允许重复声明

  3. 值不允许修改

  4. 块儿级作用域

注意: 对象属性修改和数组元素变化不会出发const错误

声明对象类型使用const,非对象类型声明选择let

变量的解构赋值!

ES6允许按照一定模式从数组和对象中提取值,对变量进行赋值,这被称为解构赋值

频繁使用对象方法、数组元素,就可以使用解构赋值形式

//数组的解构赋值
const arr = ['张学友''刘德华''黎明''郭富城'];
let [zhang, liu, li, guo] = arr;
//console.log(zhang, liu, li, guo);

//对象的解构赋值
const lin = {
    name'林志颖',
    tags: ['车手''歌手''小旋风''演员']
};
let {name, tags} = lin;
//console.log(name);
//console.log(tags);

//复杂解构
let wangfei = {
    name'王菲',
    age18,
    songs: ['红豆''流年''暧昧''传奇'],
    history: [
        {name'窦唯'},
        {name'李亚鹏'},
        {name'谢霆锋'}
    ]
};
let {songs: [one, two, three], history: [first, second, third]} = wangfei;
//console.log(two); 
//console.log(songs); × 解得了songs里面数组但不能直接输出songs

模板字符串!

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

// 定义字符串,直接使用换行符
let str = `<ul>
        <li>沈腾</li>
        <li>玛丽</li>
        <li>魏翔</li>
        <li>艾伦</li>
    </ul>`
;

// 变量拼接,进行变量拼接
let star = '王宁';
let result = `${star}在前几年离开了开心麻花`;
**当遇到字符串与变量拼接的情况使用模板字符串**

简化对象写法!

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

let name = 'Doris';
let slogon = '永远追求行业更高标准';
let improve = function ({
    console.log('可以提高你的技能');
}
//属性和方法简写
let atguigu = {
    name,
    slogon,
    improve,
    change() {console.log('可以改变你')}
};

箭头函数!

ES6 允许使用「箭头」(=>)定义函数。

箭头函数的注意点:

  1. 箭头函数this指向声明时所在作用域下 this 的值

  2. 箭头函数不能作为构造函数实例化

  3. 箭头函数内没有arguments

  4. 如果形参只有一个,则小括号可以省略

  5. 函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果

//1. 通用写法
let fn = (arg1, arg2, arg3) => {
    return arg1 + arg2 + arg3;
}

//2. 省略小括号的情况
let fn2 = num => {
   return num * 10;
};

//3. 省略花括号的情况
let fn3 = score => score * 20;

//4. this指向声明时所在作用域中 this 的值
let fn4 = () => {
    console.log(this);
}
let school = {
    name'尚硅谷',
    getName(){
        let fn5 = () => {
            console.log(this);
        }
        fn5();
    }
};

注意:箭头函数不会更改this指向,所以非常适合设置与this无关的回调,比如数组回调、定时器回调,不适合事件回调与对象方法。

rest参数!

ES6引入rest参数,用于获取函数的实参,用来代替arguments

rest参数适合不定个数参数函数的场景

//作用与 arguments 类似
function add(...args){
    console.log(args);
}
add(1,2,3,4,5);

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

spread扩展运算符!

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

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

//展开对象
let skillOne = {
    q'致命打击',
};
let skillTwo = {
    w'勇气'
};
let skillThree = {
    e'审判'
};
let skillFour = {
    r'德玛西亚正义'
};
let gailun = {...skillOne, ...skillTwo,...skillThree,...skillFour};
console.log(gailun);

Symbol

Symbol基本使用

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

Symbol特点
  1. Symbol的值是唯一的,用来解决命名冲突的问题

  2. Symbol值不能与其他数据进行运算

//创建 Symbol
let s1 = Symbol();
console.log(s1, typeof s1);

//添加标识的 Symbol
let s2 = Symbol('doris');
let s2_2 = Symbol('doris');
console.log(s2 === s2_2);

//使用 Symbol for 定义
let s3 = Symbol.for('star');
let s3_2 = Symbol.for('star');
console.log(s3 === s3_2);

Symbol类型唯一合理的用法是用变量存储 symbol的值,然后使用存储的值创建对象属性

Symbol内置值:除了定义自己使用的 Symbol 值以外,ES6 还提供了11个内置的Symbol值,指向语言内部使用的方法

迭代器

迭代器是一种接口,为各种不同的数据结构提供统一的访问机制

  1. ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费

  2. 原生具备iterator接口的数据(可用for of遍历)

​ Array、Arguments、Set、Map、String、TypeArray、NodeList

工作原理

​ a) 创建一个指针对象,指向当前数据结构的起始位置

​ b) 第一次调用对象的next方法,指针自动指向数据结构的第一个成员

​ c) 接下来不断调用next方法,指针一直往后移动,直到指向最后一个成员

​ d) 每调用next方法返回一个包含value和done属性的对象

需要自定义遍历数据的时候,要想到迭代器。

Promise!

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

Set

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

  1. size 返回集合的元素个数

  2. add 增加一个新元素,返回当前集合

  3. delete 删除元素,返回boolean 值

  4. has 检测集合中是否包含某个元素,返回boolean值

  5. clear 清空集合,返回undefined

Map(缓存)

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

  1. size 返回Map的元素个数

  2. set 增加一个新元素,返回当前Map

  3. get 返回键名对象的键值

  4. has 检测Map中是否包含某个元素,返回boolean值

  5. clear 清空集合,返回undefined

class类

知识点:

  1. class声明类

  2. 必须用constructor定义构造函数初始化

  3. extends继承父类

  4. super调用父级构造方法

  5. static定义静态方法和属性

  6. 父类方法可以重写

class Phone {
    //构造方法 只能有一个且只能constructor
    constructor(brand, color, price) {
        this.brand = brand;
        this.color = color;
        this.price = price;
    }

    //对象方法
    call(someone) {
            console.log(`我可以给 ${someone} 打电话!!!`);
        }
        sendMessage(someone){
            console.log(`我可以给${someone}发送短信`);
        }
    }

    const jinli = new Phone('金力''红色'599);
    console.log(jinli);
类的继承
//父类
class Phone {
    //构造方法
    constructor(brand, color, price) {
        this.brand = brand;
        this.color = color;
        this.price = price;
    }
    //对象方法
    call(someone) {
            console.log(`我可以给 ${someone} 打电话!!!`);
        }
        sendMessage(someone){
            console.log(`我可以给${someone}发送短信`);
        }
    }

//子类
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(someone){
        console.log(`我可以和${someone}进行视频通话!!`);
    }
    //静态方法
    static run(){
        console.log('我可以运行程序')
    }
    static connect(){
        console.log('我可以建立连接')
    }
}
//实例化对象
const Nokia = new Phone('诺基亚''灰色'230);
const iPhone6s = new SmartPhone('苹果''白色'6088'4.7inch','500w');
//调用方法
iPhone6s.call('doris');  //我可以和doris进行视频通话!!
//调用子类方法
iPhone6s.playGame();  //我可以玩游戏!!
//调用重写方法
iPhone6s.call();   //我可以进行视频通话!!
//调用静态方法
SmartPhone.run();   //我可以运行程序

类内部属性的getter和setter语法

class Phone{
    get price(){
       return 2999;
   }

   set price(v){
      this.jiage = v;
    }
   static get size(){
      return '5.5inch';
    }
}
let chuizi = new Phone();
//属性的获取
// console.log(chuizi.price);
//属性的设置
// chuizi.price = 1599;
//属性的获取
console.log(Phone.size);

数值扩展

ES6 提供了二进制和八进制数值的新的写法,分别用前缀0b(二进制)和0o(八进制)表示。

Number.isFinite() 与Number.isNaN()

Number.isFinite() 用来检查一个数值是否为有限

Number.isNaN() 用来检查一个值是否为NaN

Number.parseInt() 与Number.parseFloat()

ES6 将全局方法parseInt和parseFloat,移植到Number对象上面,使用不变。

Math.trunc

用于去除一个数的小数部分,返回整数部分。

Number.isIntege

Number.isInteger() 用来判断一个数值是否为整数

对象扩展

ES6新增了一些Object对象的方法

  1. Object.is 比较两个值是否严格相等,与『===』行为基本一致(+0 与 NaN)

  2. Object.assign 对象的合并,将源对象的所有可枚举属性,复制到目标对象

  3. __proto__、setPrototypeOf、 setPrototypeOf可以直接设置对象的原型

浅拷贝

创建一个新的对象,把原有的对象属性值,完整地拷贝过来。其中包括了原始类型的值,还有引用类型的内存地址,所以如果其中一个对象改变了这个地址,就会影响到另一个对象

//直接复制
let arr = [1234];
const newArr = arr;
newArr[0] = 521;
console.log(arr); // newArr直接覆盖arr数据 
console.log(newArr); // arr和newArr输出 [ 521, 2, 3, 4 ] 

//数组
let arr = [{name:'doris'},1,2,3,4];
//1、concat
let newArr = [].concat(arr);
newArr[0].name = 'Doris';
console.log(arr)
console.log(newArr) // [ { name: 'Doris' }, 1, 2, 3, 4 ]
//2、slice
let newArr = arr.slice(0);
 newArr[0].name = 'Doris';
 console.log(arr)
 console.log(newArr) // [ { name: 'Doris' }, 1, 2, 3, 4 ]
//3、扩展运算符
let newArr = [...arr];
 console.log(arr)
 console.log(newArr) // [ { name: 'doris' }, 1, 2, 3, 4 ]

//对象
 //使用assign方式创建对象
 const school = {
        name:"ten",
        pos:['北京','上海','深圳']
    }
    const newSchool = Object.assign({},school);
 newSchool.pos[0] = 'beijing';
 console.log(school);
 console.log(newSchool); // { name: 'ten', pos: [ 'beijing', '上海', '深圳' ] }

深拷贝

将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象

JSON 转换(好处:简单;坏处:无法深拷贝函数等特殊值)

递归(好处:能够实现完整的深拷贝;坏处:需要对递归有清醒掌握)

JSON实现深拷贝
  • stringifyf 将JS对象对华为JSON格式的字符串
  • parse 将JSON格式的字符串转化为JS对象
const school = {
    name:'doris',
    pos:['上海','北京'],
    founder:{
        name:'大姐'
    },
    //缺陷:不能复制方法
    //change: function(){
    //    console.log('改变');
    //}
}
//将对象转为JSON格式的字符串
let str = JSON.stringify(school);
//将对象转为JS对象
let newSchool =JSON.parse(str);
//测试
newSchool.pos[0] = 'beijing'
console.log(school); // {name:'doris', pos:['上海','北京'], founder:{name: '大姐'}}
console.log(newSchool); // {name:'doris', pos:['beijing','北京'],founder:{ name: '大姐'}}
递归深拷贝
    const school = {
        name:'doris',
        pos:['上海','北京','深圳'],
        founder:{
            name:'大姐'
        },
        changefunction(){
           console.log('改变');
        }
    }
//递归深拷贝原理
    //创建数据容器
    const newSchool = {};
    //name
    newSchool.name = school.name;
    //pos
    newSchool.pos = [];
    newSchool.pos[0] = school.pos[0];
    newSchool.pos[1] = school.pos[1];
    newSchool.pos[2] = school.pos[2];
    //founder
    newSchool.founder = {};
    newSchool.founder.name = school.founder.name;
    //方法
    newSchool.change = school.change.bind(newSchool);

    newSchool.pos[0] = 'beijing';
    console.log(school);
    console.log(newSchool); 
    // newSchool输出 
    // name: 'doris',
    // pos: [ 'beijing', '北京', '深圳' ],
    // founder: { name: '大姐' },
    // change: [Function: bound change]

更多知识点尽在:https://es6.ruanyifeng.com/#docs/intro

分类:

前端

标签:

JavaScript

作者介绍

d
doris
V1