ES6——let const Symbol 解构赋值

文章目录

一.let const

(一)let

1.声明的变量只能在当前作用域的内部有效(作用域其实就是{})

var 全局范围内有效(因为var声明的变量在Windows的整个对象上)

例子:
ES6——let const Symbol 解构赋值
因为let出了当前作用域会无效,for循环每走一次,就相当于一个代码作用域。下一次循环就又是另一个代码作用域了。

变量 i 是用 var 声明的,在全局范围内有效,所以全局中只有一个变量 i, 每次循环时,setTimeout 定时器里面的 i 指的是全局变量 i ,而循环里的十个 setTimeout 是在循环结束后才执行,所以此时的 i 都是 10。

变量 j 是用 let声明的,当前的 j 只在本轮循环中有效,每次循环的 j 其实都是一个新的变量,所以 setTimeout 定时器里面的 j 其实是不同的变量,即最后输出 12345。
(若每次循环的变量 j 都是重新声明的,如何知道前一个循环的值?这是因为 JavaScript引擎内部会记住前一个循环的值)。

2.不能重复声明,只能声明一次

3.不存在变量提升 否则报错
ES6——let const Symbol 解构赋值

(二)const

(1)声明的都是常量(只能读,不能设置的只读变量)

const 声明一个只读变量,声明之后不允许改变。意味着,一旦声明必须初始化,否则会报错。

const 如何做到变量在声明初始化之后不允许改变的?
其实 const 其实保证的不是变量的值不变,而是保证变量指向的内存地址所保存的数据不允许改动。此时,你可能已经想到,简单类型和复合类型保存值的方式是不同的。是的,对于简单类型(数值 number、字符串 string 、布尔值 boolean),值就保存在变量指向的那个内存地址,因此 const 声明的简单类型变量等同于常量。而复杂类型(对象 object,数组 array,函数 function),变量指向的内存地址其实是保存了一个指向实际数据的指针,所以 const 只能保证指针是固定的,至于指针指向的数据结构变不变就无法控制了,所以使用 const 声明复杂类型对象时要慎重。

* 如果用const定义一个对象,可以修改对象的属性吗?
可以!
ES6——let const Symbol 解构赋值

(2)暂时性死区

即代码块开始到变量声明语句完成之间的区域

如果代码区块中存在 let 和 const 命令声明的变量,这个区块对这些变量从一开始就形成了封闭作用域。直到声明语句完成,这些变量才能被访问(获取或设置),否则会报错

二、解构赋值

相同的结构对应赋值

可详细了解:ES6——变量解构赋值

1.数组解构赋值

  • 扩展运算符…
    [把一个数组拆成一堆]
    (只用于部署了Iterator接口的类似数组对象)

把数组取为单个值:

let arr=[1,2,3,4,5];
console.log(...arr);  //1 2 3 4 5

注意:在解构赋值中使用扩展运算符,只能放在最后面

let [a,b,...c]=[1,2,3,4,5,6];
console.log(a, b, c);  //1 2  (4) [3, 4, 5, 6]
  • 默认解构值
    ES6——let const Symbol 解构赋值

2.对象解构赋值

(1)对象解构赋值的内部机制,实际上是先找到同名属性,然后再赋值给同名的变量,真正被赋值的是后者,而不是前者。

	var {foo:baz} = {bar:"mouse",foo:"lion"};
	console.log(baz); //lion
	console.log(foo); //error:foo is not defined

(2)es6中 当key和value一致时,可简写

	var {a,b} = {b:"cat",a:"dog"};
	console.log(a); //dog
	console.log(b); //cat

就是下面的简写:

	var {a:a,b:b} = {a:"dog",b:"cat"};
	console.log(a); //dog
	console.log(b); //cat

(3)对象结构也能使用扩展运算符

    let {a,b,...c}={a:1,b:2,c:3,d:4};
    console.log(a, b, c);  //1 2 {c: 3, d: 4}

3.函数解构赋值

(1)传递数组参数

    let method=function(a,b,c){
        console.log(a, b, c);
    }
    let arr=[1,2,3];
    //方法一
    method(...arr);  //1 2 3
    //方法二
    method.apply(null,arr);  //1 2 3

(2)多层数组

    let arr=[[1,2],[3,4],[5,6]];
    arr.map(function ([a,b]) {
        console.log(a, b);
    })

ES6——let const Symbol 解构赋值

4.变量声明不能使用()

即解构赋值声明变量时, 等号左边不能使用圆括号

三、新增数据类型 Symbol

声明的变量时独一无二的,主要用来定义对象的唯一属性名

它的出现我认为主要是为了解决可能出现的全局变量冲突的问题

1.独一无二

    let sym=Symbol("abc");
    let sym1=Symbol("abc");
    console.log(sym,sym1);  //Symbol(abc) Symbol(abc)
    console.log(sym == sym1);  //false

2.Symbol在对象中的使用

(1)方法一 正常操作

    let sys=Symbol('name');
    let obj={};
    obj[sys]="唯一值";
    console.log(obj);  //{Symbol(name): '唯一值'}
    
    //不能直接 对象.属性 获取值
    console.log(obj.sys); //undefined
    console.log(obj[sys]);  //唯一值

(2)方法二 字面量操作

let syObject = {};
syObject[sy] = "kk";
 
syObject[sy];  // "kk"
syObject.sy;   // undefined

Symbol 作为对象属性名时不能用.运算符,要用方括号
因为.运算符后面是字符串,所以取到的是字符串 sy 属性,而不是 Symbol 值 sy 属性。

    /*let sys=Symbol("list");
    let obj={
        sys:'abc'  //这样写不解析
    }
    console.log(obj);  //{sys: 'abc'}*/
    
    //对象属性字面量(对象的属性是变量)
    let sys=Symbol("list");
    let obj={
        [sys]:'abc'   //对象属性是变量,解析直接[]
    }
    console.log(obj);  //{Symbol(list): 'abc'}

(3)方法三 原生js操作

Object.defineProperty() 方法
会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象

Object.defineProperty(obj, prop, descriptor)
参数:(1)obj:要定义属性的对象。
(2)prop:要定义或修改的属性的名称或 Symbol 。
(3)descriptor:要定义或修改的属性描述符。
返回值:被传递给函数的对象

在ES6中,由于 Symbol类型的特殊性,用Symbol类型的值来做对象的key与常规的定义或修改不同,而Object.defineProperty 是定义key为Symbol的属性的方法之一

    //通过原生js操作对象属性赋值
    let sys=Symbol('list');
    let obj={};
    Object.defineProperty(obj,sys,{
        value:"唯一值"
    })
    console.log(obj); //{Symbol(list): '唯一值'}

3.Symbol.for()

Symbol.for() 类似单例模式【只返回一次】
首先会在全局搜索被登记的 Symbol 中是否有该字符串参数作为名称的 Symbol值, 如果有即返回该 Symbol 值;
若没有则新建并返回一个以该字符串参数为名称的 Symbol 值,并登记在全局环境*搜索

    //创建值时去全局环境找,当前值是否创建过
    // 如果创建过,直接取值返回
    // 如果全局环境没有,创建返回
    let sys=Symbol('abc');
    console.log(sys);  //Symbol(abc)
    
    let sys1=Symbol.for('abc');
    console.log(sys1);  //Symbol(abc)
    console.log(sys === sys1); //false
    
    let sys2=Symbol.for('abc');
    console.log(sys1 === sys2); //true

4.keyFor

    //keyFor 监测symbol值是否之前登记过
    //登记过就返回值 没有登记过直接返回undefined
    let sys=Symbol.for("abc")
    console.log(Symbol.keyFor(sys));  //abc
    console.log(Symbol.keyFor(Symbol('ABC'))); //undefined

5.description 直接通过属性获取描述

    let sys=Symbol('abc');
    console.log(sys.toString());  //Symbol(abc)
    console.log(String(sys));  //Symbol(abc)

    //es9 直接通过属性可以获取描述
    console.log(sys.description);  //abc
上一篇:EXPORT_SYMBOL的正常使用


下一篇:实验三