es6(上)

本文介绍了JavaScriptES6中的新特性,包括let和const块级绑定,解释了它们的块级作用域和如何解决经典的for循环闭包问题。此外,还详细阐述了解构赋值在数组、对象和参数中的应用。同时,文章讨论了Symbol的基本用法,特点以及在避免属性名覆盖和模拟私有属性方面的使用场景。最后提到了模板字符串的增强功能,如插入变量和表达式。
摘要由CSDN通过智能技术生成

目录

1.块级绑定

块级作用域

经典的for循环闭包问题可以使用let 解决

全局绑定

2. 解构:更方便的数据访问

数组解构

对象解构

参数解构

3.符号-Symbol

特点:

 方法:

1、Symbol.for()

Symbol()和Symbol.for()的区别:

2、Symbol.keyFor()

属性:

使用场景

避免属性名覆盖

模拟private 关键字来声明类的私有方法和私有变量的

4. 字符串

字符串插入变量和表达式


1.块级绑定

新增加了两个重要的 JavaScript 关键字: letconst

let 声明的变量只在 let 命令所在的代码块内有效

const 声明一个只读的常量,一旦声明,常量的值就不能改变。

let和const变量不会被提升,只有先声明才能够访问。

暂时性死区

ES6 明确规定,代码块内如果存在 let 或者 const,代码块会对这些命令声明的变量从块的开始就形成一个封闭作用域。代码块内,在声明变量 PI 之前使用它会报错。

let和const都有自己的块级作用域

注:通常情况下,如果变量不需要被重新赋值,应该使用 const 声明常量;如果变量需要被重新赋值,应该使用 let 声明可变变量。

块级作用域

正常情况下,JS 引擎在编译代码阶段会生成全局执行上下文和函数执行上下文。这其中,每个上下文又分为了两个部分:变量环境和词法环境

var a = 0
let b = 1
function foo() {
    var a = 1
    let b = 2
    if (true) {
        let b = 3
        console.log(a, b)
    }
}
foo()                                   // 1, 3

  1. 使用 var 关键字声明的变量、及函数声明,会被放入变量环境中
  2. 使用 let 及 const 关键字声明的变量和常量会被放入词法环境中
  3. 词法环境内部也类似于一个栈结构,每一个块结构(即有一对大括号,如条件句、循环等)内的变量和常量会单独保存(使用 var 关键字声明的不会)。
  4. 所以,如上面的例子,函数 foo 的词法环境里,有两个区域。下面的区域保存了函数体内使用 let 声明的变量,上面的区域保存了 if 语句中使用 let 声明的变量。所以即使它们都叫做 b,但却是两个不同的变量。

经典的for循环闭包问题可以使用let 解决

for (var i = 0; i < 10; i++) {
  setTimeout(function(){
    console.log(i);
  })
}
// 输出十个 10
for (let j = 0; j < 10; j++) {
  setTimeout(function(){
    console.log(j);
  })
}
// 输出 0123456789

全局绑定

当在全局作用域上使 用 var 时,它会创建一个新的全局变量,并成为全局对象(在浏览器中是 window )的一 个属性,然而若你在全局作用域上使用 let 或 const ,虽然在全局作用域上会创建新的绑定,但不 会有任何属性被添加到全局对象上。

// 在浏览器中 
let RegExp = "Hello!"; console.log(RegExp); // "Hello!"
console.log(window.RegExp === RegExp); // false 
const ncz = "Hi!"; console.log(ncz); // "Hi!" console.log("ncz" in window); // false

2. 解构:更方便的数据访问

解构赋值是对赋值运算符的扩展,是一种针对数组或者对象进行模式匹配,然后对其中的变量进行赋值。 解构的源,解构赋值表达式的右边部分。解构的目标,解构赋值表达式的左边部分

包括数组解构,参数解构,对象解构

数组解构

// 基本
let [a, b, c] = [1, 2, 3];
// a = 1
// b = 2
// c = 3
// 嵌套	
let [a, [[b], c]] = [1, [[2], 3]];
// a = 1
// b = 2
// c = 3
// 剩余参数
let [a, ...b] = [1, 2, 3];
//a = 1
//b = [2, 3]

对象解构

// 基本
let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
// foo = 'aaa'
// bar = 'bbb'
 
let { baz : foo } = { baz : 'ddd' };
// foo = 'ddd'
// 剩余运算符
let {a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40};
// a = 10
// b = 20
// rest = {c: 30, d: 40}
// 解构默认值
let {a = 10, b = 5} = {a: 3};
// a = 3; b = 5;
let {a: aa = 10, b: bb = 5} = {a: 3};
// aa = 3; bb = 5;

参数解构

function setObj(name, type, { age = 123 }) {
    console.log(name, type, age);
}
   setObj(1, 1, { age: 345 }); // 正常
// setObj(1, 1);// 报错

参数解构有一个怪异点:默认情况下调用函数时未给参数解构传值会抛出错误。

可以给解构的参数提供默认值来处理这种行为

function setObj(name, type, { age = 123 } = {}) {
    console.log(name, type, age);
}
//   setObj(1, 1, { age: 345 });
setObj(1, 1);

3.符号-Symbol

Symbol 是 ES6 新推出的一种基本类型,它表示独一无二的值

const s1 = Symbol();
const s2 = Symbol();
console.log(s1 === s2); // false
 
const s1 = Symbol('debug');
const str = 'debug';
const s2 = Symbol('debug');
console.log(s1 === str); // false
console.log(s1 === s2); // false
console.log(s1); // Symbol(debug)
console.log(typeof s1); // symbol

特点

  1. Symbol()不是一个完整的构造函数,因此不能通过new Symbol() 来创建(通过 new实例化的结果是一个 object对象,而不是原始类型的 symbol)
  2. Symbol不能进行隐式类型转换,但可以显式转为字符串;不能转化为数字,但可以转化为布尔值
  3. 由于Symbol值的唯一性,意味着它可以作为对象的属性名,避免出现相同属性名,产生某一个属性被改写或覆盖的情况。

 注意:Symbol作为属性名

1、不能通过点运算符访问,需要通过方括号的形式访问。

2、不能通过for...in、for...of遍历,也不会被 Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回。但是它也不是私有属性,可以通过Object.getOwnPropertySymbols()Reflect.ownKeys()方法获取对象Symbol 属性名。

let sym3 = Symbol('test');
let obj={name: 'lin', [sym3]: 'foo'};
obj[sym3];       //"foo"
JSON.stringify(obj);  //"{"name":"lin"}"
Object.keys(obj);   //["name"]
Object.getOwnPropertyNames(obj);   //["name"]
for (let key in obj) {
    console.log(key);     //name
}
Object.getOwnPropertySymbols(obj);  //[Symbol(test)]

 为什么属性两边加上[]

这是ES6引入的一个属性名表达式(计算属性),用于动态获取属性名,讲白就是你可放变量名在里面,之后通过变量去调

 方法

Symbol有两个方法,分别是Symbol.for()和Symbol.keyFor()

1、Symbol.for()

 用于将描述相同的Symbol变量指向同一个Symbol值

let a1 = Symbol.for('a');
let a2 = Symbol.for('a');
a1 === a2  // true
typeof a1  // "symbol"
typeof a2  // "symbol"
 
let a3= Symbol("a");
a1 === a3      // false

Symbol()和Symbol.for()的区别:

Symbol()和Symbol.for()都会生成新的Symbol。

Symbol()未在全局环境(Symbol的容器)中注册

Symbol.for()有在全局环境中注册,所以有注册的相当于就单例了,有注册的话直接就返回了,没注册就新创建,而Symbol()每次都是创建新的。

2、Symbol.keyFor()

Symbol.keyFor()是用来返回一个在全局环境注册过的Symbol的key

注意:未注册的Symbol是无法获取的

let a1 = Symbol.for("a");
Symbol.keyFor(a1);    // "a"
 
let a2 = Symbol("a");
Symbol.keyFor(a2);    // undefined

属性:

Symbol.prototype.description用来返回Symbol数据描述

// Symbol()定义的数据
let a = Symbol("acc");
a.description  // "acc"
Symbol.keyFor(a);  // undefined
 
// Symbol.for()定义的数据
let a1 = Symbol.for("acc");
a1.description  // "acc"
Symbol.keyFor(a1);  // "acc"
 
// 未指定描述的数据
let a2 = Symbol();
a2.description  // undefined

description属性和Symbol.keyFor()方法的区别是: description能返回所有Symbol类型数据的描述,而Symbol.keyFor()只能返回Symbol.for()在全局注册过的描述

使用场景

避免属性名覆盖

const name = Symbol('name');
const obj = {
    [name]: 'ClickPaas',
}

模拟private 关键字来声明类的私有方法和私有变量的

const speak = Symbol();
class Person {
    [speak]() {
        console.log(123)
    }
}
let person = new Person()
console.log(person[speak]())

无法在外部创建出一个相同的 speak,所以就无法调用该方法

https://juejin.cn/post/6844904056465408007


4. 字符串

模板字符串相当于加强版的字符串,用反引号 `,除了作为普通字符串,还可以用来定义多行字符串,还可以在字符串中加入变量和表达式。

let string = `Hello'\n'world`;
console.log(string); 
// "Hello'
// 'world"

字符串插入变量和表达式

变量名写在 ${} 中,${} 中可以放入 JavaScript 表达式。

let name = "Thomas";
let age = 25;
let info = `My Name is ${name},I am ${age+1} years old next year.`
console.log(info);
// My Name is Mike,I am 28 years old next year.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值