You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
主要用于声明变量,用法类似 var,但是只在声明的作用域 { } 内有效(如在作用域外使用变量将导致报错);
用 for 循环 遍历时,非常适用,可以避免一些需要闭包解决的问题; ps:
这样的问题就是因为循环一直在进行,但是 循环内部的函数一直未进行,函数内部拿到的 i 值是外部的 i , 外部的 i 值一直在变,内部的值也随着循环的进行在变化,所以最后输出的就是循环结束的条件 i == 10; 但是用 let 去代替 var 就会产生作用域,i 值 每次循环的值都只在当前循环的单独作用域内使用,所以最后输出的值会是 2;ps:
var 的有个声明提前!,但是 let 没有这个问题,所以以 let 声明的变量只能在声明之后使用(这种在语法上来说叫暂时性死区,也代表 typeof 判断值类型也不那么百分百能正确),如果在之前使用就不像 var 声明一样是undefined,会导致浏览器直接抛出错误。在之前使用 typeof 判断变量,会得出 ReferenceError let 不允许在同一作用域进行二次声明! 另外注意使用 { } 作用域才算成立!
2. const
const 也是类似 var | let 之流的声明语法,不过 const 声明的变量一般称之为常量。也就是字面上的意思,可以获取但不可赋值数据(更改),其他的作用基本与 let 一致。对于一般类型的数据,如numberstring之类的数据是指向保存值的地址,对于复合类型的数据(Array | Object)保存的就只是一个指针,对于是不是不可变的,就不可控了。所以声明常量一定要注意(就是不要随便乱用)。
当然,想让一个const声明过的复合类型的数据不可更改也可以使用 Object.freeze方法冻结对象,必要时也要冻结对象里所有的属性!ps:
1. let
主要用于声明变量,用法类似 var,但是只在声明的作用域
{ }
内有效(如在作用域外使用变量将导致报错);用
for
循环 遍历时,非常适用,可以避免一些需要闭包解决的问题; ps:这样的问题就是因为循环一直在进行,但是 循环内部的函数一直未进行,函数内部拿到的
i
值是外部的i
, 外部的i
值一直在变,内部的值也随着循环的进行在变化,所以最后输出的就是循环结束的条件i == 10
; 但是用let
去代替var
就会产生作用域,i
值 每次循环的值都只在当前循环的单独作用域内使用,所以最后输出的值会是2
;ps:var 的有个声明提前!,但是
let
没有这个问题,所以以let
声明的变量只能在声明之后使用(这种在语法上来说叫暂时性死区,也代表typeof
判断值类型也不那么百分百能正确),如果在之前使用就不像var
声明一样是undefined
,会导致浏览器直接抛出错误。在之前使用typeof
判断变量,会得出ReferenceError
let
不允许在同一作用域进行二次声明! 另外注意使用{ }
作用域才算成立!2. const
const
也是类似var
|let
之流的声明语法,不过const
声明的变量一般称之为常量。也就是字面上的意思,可以获取但不可赋值数据(更改),其他的作用基本与let
一致。对于一般类型的数据,如number
string
之类的数据是指向保存值的地址,对于复合类型的数据(Array | Object
)保存的就只是一个指针,对于是不是不可变的,就不可控了。所以声明常量一定要注意(就是不要随便乱用)。当然,想让一个
const
声明过的复合类型的数据不可更改也可以使用Object.freeze
方法冻结对象,必要时也要冻结对象里所有的属性!ps:3. Array 解构赋值以及扩展
在之前,赋值都是直接使用
=
赋值于变量,ES6
却提供了一种 “模式匹配” 的写法,只要=
两边结构一致,左边的变量会被赋予右边数据的值。ps:当然,如果对应位置没有数据的变量会是
undefined
,当然意思就是只要左边变量相应右边数据结构(能遍历的结构)位置上有数据,就可以为左边所有相应位置的变量赋值成功;但是,如果
=
右边不是数组(严格来说,不是能遍历的结构),那么将会报错;解构赋值可以在赋值之前先赋值,意义上来说就是指定默认值;得注意的是,ES6内部使用严格的相等运算符
===
,判断一个位置是否有值,所以只有当一个数组成员[a = 1] = [undefined]
(例如右边)值===
undefined
时,默认值才会生效(也就是a
会被赋值为 1),当右边的值为null
时包括空字符、0在内,默认值都将会被覆盖;对于
Array
的扩展使用方式是...
,这个叫做扩展运算符,它可以将一个数组转化成用逗号分隔的参数序列。在某些需要数组合并的时候代替 类似push
之类的方法,以及在函数的参数中使用;ps:...
展开数组,可以代替函数的apply方法,即不需要将数组转为函数的参数了。ps:
Math.max.apply(null, [1, 2, 3])
等同于Math.max(...[1, 2, 3])
等同于Math.max(1, 2, 3)
Array.prototype.push.apply([1, 2, 3], [4, 5, 6])
等同于[1, 2, 3].push([4, 5, 6])
已知数组在JS中属于引用类型,也就是复制一个值给新的变量其实复制的只是指向同一份数据的指针,修改新的变量会导致旧变量也会变化;解决办法 ps:
注意:如果将扩展运算符用于数组赋值,只能放在参数的最后一位!否则会报错
扩展运算符还可以将字符串转为真正的数组 ps:
[...'hello']
==['h', 'e', 'l', 'l', 'o']
这样的写法有个很重要的好处,就是能够正确识别四个字节的unicode
可以查询并返回正确的字符长度length
任何
Iterator
接口的对象,都可以用扩展运算符转化成真正的数组(例如,document.querySelectorAll('el')
返回的是nodeList
对象,这个并不是数组,而是一个类数组对象。这个时候可以使用扩展运算符将其转化成真正的数组)。原因在于nodeList
对象实现了Iterator
,反之没有部署Iterator
接口的类数组对象,就无法转化!有类数组对象也是有下标(索引),有 length。可以用Array.from
方法将其转化成真正的数组!Map
和Set
结构,Generator
函数: 扩展运算符内部调用的是数据结构的Iterator
接口,因此只要具有Iterator
接口的对象,都可以使用扩展运算符,比如Map
结构。ps:Generator
函数运行后,返回一个遍历器对象,因此也可以使用扩展运算符。ps:Array.from
方法用于将两类对象转为真正的数组:类似数组的对象(array-like object) 和可遍历(iterable)的对象(包括ES6新增的数据结构Set 和 Map);在实际应用中。常见的类似数组的对象是DOM操作返回的NodeList集合,以及函数内部的arguments
对象。Array.from
都可以将它们转为真正的数组。ps:但是如果一个对象没有部署
Symbol.iterator
这个接口,就无法转化;例如:Array.from({ length: 3 })
会得出[undefined, undefined, undefined]
,扩展运算符转化不了这个对象。对于还没有部署该方法的浏览器,可以使用
Array.prototype.slice
方法代替,且,Array.from
还可以接收第二个参数,作用类似于数组的map
方法,用来对每个元素进行处理,将处理后的值放入返回的数组 ps:.................loading...
lack: 不定时更新或者修改内容
注:Google搜集整理,加点个人体会
============================ END ===================================
The text was updated successfully, but these errors were encountered: