分类: 笔记

  • let、const、var

    let

    块级作用域

    let声明的变量, 有块级作用域,只能在大括号{}里使用

    好处: 避免全局变量污染

    // 块级作用域
    // 在大括号内, 用let声明的变量, 只能在大括号内使用
    if (true) {
        let myName = "Liao"
        console.log(myName) //Liao
    }
     console.log(myName) //myName is not defined
    

    先定义再使用

    let必须先定义再使用, 不然就会报错

      console.log(a) // 报错
      let a = 10
    

    不可重复声明

    let同一个作用域下, 不能重复声明同一个名字的变量

    let a = 10
    let a = 10 // 报错
    

    全局let不会挂载到window上

    避免污染window原有的全局变量

    const

    作用: 声明常量

    必须赋予初始值, 且无法修改

    其他特点和let相同

    • 块级作用域
    • 不挂载到 window 上
    • 必须先声明再使用 (没有变量声明提升)
    • 同一个作用域下, 不能重复声明同一个名字的变量

    注意

    const声明的变量, 如果存复杂类型, 存的是对象/数组的内存地址

    只要地址不改变, 可以修改指向的对象或者数组的内容

    const obj = {
      name: 'Liao',
      age: 18
    }
    // obj = {} // 报错,常量不能修改
    obj.name = 'lll' // 正确
    

    var

    var没有块级作用域, 容易造成变量污染

    全局的var会被自动挂载到 window 上, 污染 window 的变量(这不合理!)

    var a = 10
    console.log(window.a) //10
    

    var存在变量声明提升, 先使用后定义不报错! 会打印 undefined(这不合理!)

    console.log(a) // undefined
    var a = 10
    

    var就算同一个作用域下, 重复声明了相同的变量名, 也不报错(这不合理!)

    var a = 10
    var a = 20
    
    var总结
    • 没有块级作用域
    • 全局的var会污染 window 的变量
    • 先使用后定义不报错
    • 同一个作用域下, 重复声明了相同的变量名, 也不报错
  • 箭头函数

    作用: 简化匿名函数, 简化回调函数和普通函数的写法

    语法: () => {}, 小括号内书写形参, 大括号内写函数体

    let fn = (msg) => {
      console.log('Hello' + msg)
    }
    

    简化语法

    • 如果形参只有1个, 可以省略小括号
    • 方法体只有一行代码, 可以省略大括号, 省略大括号后, 默认返回此结果
    //上例中的箭头函数可简化
    let fn = msg => console.log('Hello' + msg)
    
    fn('World!')
    

    注:方法体只有一行代码,且省略了大括号,如果函数有return,则也省略。

    也就是箭头函数只有一句代码并且省略大括号时,默认带有return,再写return则会报错。

    let fn = (a,b) => {
    	return a + b
    }
    
    //可简化成
    let fn = (a,b) => a + b
    

    this指向

    箭头函数的this指向的是外层作用域this的值

    let myObj = {
      a: function () {
        console.log(this)
      },
      b: () => {
        console.log(this)
      }
    }
    myObj.a() // myObj
    myObj.b() // window
    

    其他

    • 箭头函数不能用作构造函数, 不能和new配合使用
    • 不能使用arguments
  • 剩余参数运算符、展开运算符

    …剩余参数运算符

    为了接收所有参数

    普通函数可以通过arguments获取全部参数,箭头函数没有arguments

    用于函数形参,必须放在形参最后一个!

    • 一般配合箭头函数, 因为箭头函数内不能用arguments
    • 必须出现在形参的最后面
    function youSum (a, ...args) {
      console.log(a, args)
    }
    youSum(5, 10) //5 [10]
    youSum(5, 100, 200, 300) //5 [100,200,300]
    youSum(5, 100, 200, 300, 400) //5 [100,200,300,400]
    
    let mySum = (...args) => {
      console.log(args)
    }
    mySum(10, 20, 30, 40) //[10, 20, 30, 40]
    

    …展开运算符

    用于数组[]或对象{}中, 可以将数组的项或对象的键值对展开

    展开数组

    let arr = [1, 3, 5, 7]
    console.log(...arr) // 打印数组的每一项 1,3,5,7
    拼接两个数组
    let arr1 = [1, 2, 3]
    let arr2 = [4, 5, 6]
    let newArr = [...arr1, ...arr2]
    求数组最大值
    let arr = [3, 100, 20]
    let max = Math.max(...arr3)

    展开对象

    let obj1 = {
      name: 'Liao',
      age: 18,
    }
    let obj2 = {
      money: 10000000000,
      car: "没有"
    }
    // 相当于快速浅拷贝
    let obj3 = {
      ...obj1,
      ...obj2,
      name: 'liao'
    }
    //obj3 === {name: 'Liao',age: 18,money: 10000000000,car: "没有",name: 'liao'}
    //obj3的name属性放到...obj2前面,name属性则会被覆盖
  • 对象的keys、values、entries函数

    Object.keys()

    返回一个数组

    返回的成员是参数对象自身的(不含继承的)所有可遍历属性的键名。

    const obj = { a: "aaa", b: 1};
    Object.keys(obj)  // ["a", "b"]
    

    Object.values()

    返回一个数组

    返回的成员是参数对象自身的(不含继承的)所有可遍历属性的键值。

    const obj = { a: "aaa", b: 1};
    Object.values(obj)  // ["aaa",1]
    

    Object.entries()

    返回一个数组

    返回的成员是参数对象自身的(不含继承的)所有可遍历属性的键值对。

    const obj = { a: "aaa", b: 1};
    Object.entries(obj)  // [ ["a", "aaa"], ["b", 1] ]
    

    JS中对象的keys, values,entries函数_还寝梦佳柒的博客-CSDN博客

  • 类数组对象

    一个对象如果有 length,有 index 数字属性,那它可被看成一个数组(鸭子模型:如果它走起来像鸭子,而且叫起来像鸭子,那么它就是鸭子)。

    如:{length: 5, 0: 1},这个对象既有 length 属性,又有作为 index 的 0 属性,它具有作为数组的特质,即为一个类数组对象。

    [1].slice.call({length: 1, 0:3})  // [3]
    

    上面语句生成一个 length 为 1 且 index:0 位置为 3 的数组。[1] 只是一个迷惑写法,[] 中的数字改为其他任何数字,结果都一样。实质是 Array.prototype.slice.call(),即等同于

    Array.prototype.slice.call( { length: 1, 0:3 } )
    [].slice.call( { length: 1, 0:3 } ) 
    

    作者:不要面包要蛋糕 链接: 类数组对象 – 简书 

    来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • for…in和for…of

    for…in

    遍历对象

    获得对象的键名

    for...in是为遍历对象而设计的,不适用于遍历数组。

    遍历数组的缺点
    • 数组的键名是数字,但是for…in循环是以字符串作为键名“0”、“1”、“2”等等。
    • for…in循环不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型链上的键。
    • 某些情况下,for…in循环会以任意顺序遍历键名。
    语法

    for (variable in object) {...}

    for…in语句以任意顺序遍历一个对象自有的、继承的、可枚举的、非Symbol的属性。对于每个不同的属性,语句都会被执行。

    for…in遍历哪些属性?

    • 自有的:自带的属性
    • 继承的:原型链上的属性(如果不需要继承的属性可用Object.keys()方法)
    • 可枚举的
    • 非Symbol的属性

    for…of

    获得键值

    let arr = ['a', 'b', 'c', 'd'];
     
    for (let a of arr) {
      console.log(a); // a b c d
    }
    

    可遍历包括数组、Set 和 Map 结构、某些类似数组的对象(比如arguments对象、DOM NodeList 对象)、后文的 Generator 对象,以及字符串。

    for...of可以响应breakcontinuereturn语句

    不可遍历普通对象(报错:obj is not iterable(obj不可迭代))

    for...of循环调用遍历器接口,数组的遍历器接口只返回具有数字索引的属性。这一点跟for...in循环也不一样。

    例:

    let arr = [3, 5, 7];
    arr.foo = 'hello';
     
    for (let i in arr) {
      console.log(i); // "0", "1", "2", "foo"
    }
     
    for (let i of arr) {
      console.log(i); //  "3", "5", "7"
    }
    

    for…of 循环(ES6)_zhangbin0027的博客-CSDN博客

    JavaScript对象遍历 – SegmentFault 思否

    彻底搞清楚 Iterator(遍历器)接口_毛小星的博客-CSDN博客

  • 闭包

    作用:实现数据私有

    内层函数, 引用外层函数上的变量, 就可以形成闭包。

    一个小例子

    function count() {
    	let num = 0 //只能在count函数中访问到
    	function add() {
    		num++
    		console.log(num)
    	}
    //执行count函数会返回add函数,相当于外面可以执行add函数,且不能直接访问修改num
    	return add
    }
    
    //addFN等价于返回的add函数
    let addFN = count()
    addFN() //1
    

    给闭包传值

    function sum(x) {
    	return function (y) {
    		return console.log(x + y)
    	}
    }
    
    //此时传值给sum函数的x
    let fn = sum(3) 
    
    //此时传值给内部匿名函数的y
    fn(10) 
    
    // 控制台结果为13
    
  • 对象键值对简化写法

    对象属性名, 属性值同名, 可以简写, 只写一个

    方法可以将 :function 省略不写

    let x = 10;
    let y = 20;
    let obj = {
      x,
      y,
      getPosition() {
        return obj.x
      }
    }
    
  • 解构赋值

    概念: ES6 允许 按照一个模式, 从目标结构 (数组/对象) 中提取值, 赋予给变量, 解构的目的方便取值.
    目的: 优化取值的过程

    数组的解构

    • 完全解构
    • 不完全解构
    let arr = ["春天", "夏天", "秋天", "冬天"]
    
    let [spr, sum, aut, win] = arr // 完全解构
    
    let [spr, , aut] = arr // 不完全解构
    

    对象的解构

    • 基本解构
    • 解构重命名

    解构赋值只要两边解构相同就行,所以对象也是可以解构赋值的。但是需要注意的是对象和数组的解构有一个很大的区别:对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

    let obj = {
      name: 'liao',
      age: 18,
      desc: '不错'
    }
    
    // 1. 基本解构
    let { name, age, desc } = obj
    
    // 2. 解构重命名 {变量名: 新的变量名}
    let { name: myname, age: myage, desc: mydesc } = obj
    
    // 3. 解构默认值
    let { name, age, desc, girl = '小花' } = obj
    
    // 4. 重命名 + 默认值
    let { name, age, desc, girl: myGirl = '小花' } = obj
    
    使用解构赋值的时候,要注意声明变量的作用域问题
    // 错误的写法
    let x;
    {x} = {x: 1};
     
    // 正确的写法
    let x;
    ({x} = {x: 1});
    

    上面的例子中错误的原因是{x}被认为是一个块级作用域,导致解构失败,我们在使用解构要尽量避免这种大括号直接在行首的情况。

    https://blog.csdn.net/bjhan_csdn/article/details/97389320

  • Map()与Set()

    Map()

    Map是一个带键的数据项的集合,就像object一样。但是它们最大的差别是Map允许任何类型的键。

    方法和属性

    • new Map() —- 创建map
    • map.set(key,value) —- 根据键存储值
    • map.get(key) —- 根据键来返回值,如果map中不存在对应的key,则返回undefined
    • map.has(key) —- 如果key存在则返回true,负责返回false
    • map.delete(key) —- 删除指定键的值
    • map.clear() —- 清空map
    • map.size —- 返回当前元素个数
    let map=new Map() 
    
    map.set('1','se') //根据键储存值 返回 Map(1) {"1" => "se"}
    
    map.get('1') //根据键返回值,如果不存在返回undefind 返回se
    
    map.has('1') //如果key存在返回true
    
    map.delete('1') //删除指定键的值 返回true
    
    map.clear() //清空 返回undefind
    
    map.size //返回当前元素个数 返回0
    

    https://blog.csdn.net/qq_52959651/article/details/110275146

    Set()

    • 是一组key的集合,但不存储value。(或者说key、value相同)
    • 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用。Set中,key不能重复。如果出现重复的key,Set会自动过滤。Set没有索引,它的键和值是一个。
    • Set()是一个类似数组解构,但它不是数组。它本身就是一个构造函数。
    • 它最主要的作用是去重。
    • 可以使用Array.from()把它变成一个数组。
    • 通过展开运算符(…)可以把Set集合转换成一个数组。
    let set = new Set([1, 2, 3, 3, 3, 4, 5]),
    array = [...set] 
    console.log(array)  // [1,2,3,4,5]
    

    方法和属性

    • set.add("a")添加一个元素
    • set.delete("a")删除一个元素
    • set.size获取元素的数量
    • set.clear()清除对象中的所有元素。
    • set.has("a")判断s对象中是否有某个元素,返回true或false
    //实例化一个Set对象
    var set =new Set() 
    
    //Set对象通过add方法添加元素
    set.add('3')
    set.add('3') //注意3和'3'是不同的元素
    set.add('apple') 
    console.log(s) //打印结果:Set(3) {3, "3", "apple"}
    
    //使用delete可以删除元素
    set.delete('apple') 
    console.log(s)  //打印结果:Set(2) {3, "3"}
    
    //清除set对象中的所有元素。
    set.clear() 
    

    例:可以用多个add加入元素

    set.add(1).add('哈').add('apple') 
    console.log(s)  //Set(3) {1, "哈", "apple"}
    //Set括号中数字代表set中有几个元素
    

    https://blog.csdn.net/qq_42238554/article/details/86609429