js基础复习(一)

408 阅读4分钟

今天起复习ES6-ES10的新知识,为以后做准备。

1.let

1.1 let声明的变量不会挂载到window上

var a = 3
let b = 4

console.log(a, b) // 3 4
console.log(window.a, window.b) // 3 undefined

1.2 let不能重复声明变量

// 可行
var a = 3
var a = 4

// 报错
let b = 4
let b = 5

1.3 let不存在变量提升

2.const

2.1 const声明的变量不会挂载到window上

2.2 const不能重复声明变量

2.3 const不存在变量提升

2.4 const声明的常量不能重新赋值

// 报错
const a = 1
a = 2 

// 报错 const声明必须赋值
const b
b = 1

3.遍历

3.1 es5中遍历的方法

3.1.1 for循环

let arr = [1, 2, 3, 4]

for (let i = 0; i < arr.length; i++) {
    console.log(arr[i])
}

3.1.2 forEach

let arr = [1, 2, 3, 4]

arr.forEach((item) => {
    console.log(item)
})

forEach问题,不能continue和break,如果想终止循环可以通过抛出异常

let arr = [1, 2, 3, 4]

try {
    arr.forEach((item) => {
        if (item === 2) {
            throw new Error('')
        }
        console.log(item)
    })
} catch (e) {
    console.log('循环结束')
}

3.1.3 every

every也可以遍历,也不支持continue和break,但是可以通过return false终止循环(默认返回false)

let arr = [1, 2, 3, 4]

arr.every((item) => {
    if (item === 3) {
        return false
    }
    console.log(item)
    return true
})

3.1.4 for...in(为对象设计的)

支持continue和break

let arr = [1, 2, 3, 4]

for (let index in arr) {
    console.log(index, arr[index])
}

由于数组是对象,所以可以给数组新增属性,给数组新增属性之后,for...in可以把a也遍历出来,这是一个瑕疵。 而且循环时我们定义的index是字符串。

let arr = [1, 2, 3, 4]
arr.a = 8
for (let index in arr) {
    console.log(index, arr[index]) // 会把a和8打印出来
}

for...in遍历对象需要配合hasOwnProperty使用

let obj = {
    a: 1,
    b: 2
}

for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
        console.log(obj[key])
    }
}

3.2 es6中的遍历方法

3.2.1 for...of

for...of可以遍历任何可遍历的数据结构

for (let item of arr) {
    console.log(item)
}

4.Array

4.1 Array.from

涉及到的问题是如何把伪数组转换成数组
NodeList(选中的DOM集合)
arguments(函数参数集合)
他们在特性上像数组,但是不能直接使用数组的方法。
伪数组有两个特征,第一个特征是按照索引储存属性,第二个特征是有length属性

// 这就是个伪数组
{
    0: 'a',
    1: 'b',
    length: 2
}

4.1.1 es5方法

let args = Array.prototype.slice.call(arguments)
let imgs = Array.prototype.slice.call(document.querySelectorAll('img'))

4.1.2 es6方法

let args = Array.from(arguments)
let imgs = Array.from(document.querySelectorAll('img'))

4.1.3 Array.from详解

Array.from(arrayLike, mapFn, thisArg)

第一个参数是需要转换的伪数组,第二个参数是一个函数,每次遍历都会执行,第三个参数是this指向

let arr = Array.from({length: 5}, function () {return 1}, null)

4.2 Array.of

把几个元素放到数组中,不需要像以前每个都push

let array = Array.of(1, 2, 3, 4, 5) // [1, 2, 3, 4, 5]

4.3 Array.fill

4.3.1 填充数组

let array = Array(5).fill(1) // [1, 1, 1, 1, 1]

4.3.2 fill参数

Array.fill(value, start, end) // 包括start不包括end

4.4 查找数组

4.4.1 es5中在数组中找到某一项

数组遍历完才停止,所以会把符合条件的值都找到

let arr = [1, 2, 3, 4]
let find = arr.filter((item) => {
    return item ===  3
})
console.log(find) // [3]

let find2 = arr.filter((item) => {
    return item ===  6
})
console.log(find2) // []

let find3 = arr.filter((item) => {
    return item % 2 === 0
})
console.log(find3) // [2, 4]

缺点是,如果数组非常大,我们在数组中寻找某一项的话,filter会把数组遍历完

4.4.2 es6中的find

找到第一个符合条件的就停止

let arr = [1, 2, 3, 4]
let find = arr.find((item) => {
    return item === 3
})
console.log(find) // 3 

let find2 = arr.find((item) => {
    return item === 6
})
console.log(find2) // undefined

let find3 = arr.find((item) => {
    return item % 2 === 0
})
console.log(find3) // 2

4.4.3 es6中的findIndex

let arr = [1, 2, 3, 4]
let find = arr.findIndex((item) => {
    return item === 3
})
console.log(find) // 2

5.类

5.1 ES5中的类

let Animal = function (type) {
    this.type = type
}

Animal.prototype.eat = function () {
    console.log('eat')
}

let cat = new Animal('cat')
let dog = new Animal('dog')

5.2 ES6中的类

ES5类的语法糖

class Animal {
    constructor (type) {
        this.type = type
    }
    
    eat () {
        console.log('eat')
    }
}

let cat = new Animal('cat')
let dog = new Animal('dog')

5.3 属性读写(getter setter)

getter

let _age = 4
class Animal {
    constructor (type) {
        this.type = type
    }
    
    get age () {
        return _age
    }
    
    eat () {
        console.log('eat')
    }
}

let dog = new Animal('dog')
console.log(dog.age) // 4
dog.age = 11
console.log(dog.age) // 4

setter

let _age = 4
class Animal {
    constructor (type) {
        this.type = type
    }
    
    get age () {
        return _age
    }
    
    set age (val) {
        if (val > 4 && val < 7) {
            _age = val   
        }
    }
    
    eat () {
        console.log('eat')
    }
}

let dog = new Animal('dog')
console.log(dog.age) // 4
dog.age = 11
console.log(dog.age) // 4
dog.age = 6
console.log(dog.age) // 6

目的是控制一个属性只读,或者是有条件的更改

5.4 操作方法(静态方法)

class Animal {
    constructor (type) {
        this.type = type
    }
    
    eat () {
        Animal.walk() // 静态方法必须用类调用
        console.log('eat')
    }
    
    static walk () {
        console.log('walk')
    }
}

let dog = new Animal('dog')
dog.eat() // walk  eat
dog.walk() // dog.walk is not a function

eat是实例对象的方法
walk是静态方法
如果方法依赖于实例对象的属性,就用实例对象方法。没有依赖就用静态方法,静态方法是拿不到实例对象中的属性的。

5.5 继承

ES5中,继承的步骤是:(不止这一种实现方法) (1)在子类中执行一遍父类的构造函数 (2)将子类原型指向父类

function Animal (type) {
    this.type = type
}

Animal.prototype.eat = function () {
    console.log('eat')
}

function Dog () {
    Animal.call(this, 'dog')
    this.run = function () {
        console.log('run')
    }
}
Dog.prototype = Animal.prototype

ES6中继承:也要先执行父类的构造函数(子类构造函数如果是空的,可以省略constructor),super()必须放在构造函数第一行。

class Animal {
    constructor (type) {
        this.type = type
    }
    
    eat () {
        Animal.walk() // 静态方法必须用类调用
        console.log('eat')
    }
}

class Dog extends Animal {
    constructor (type) {
        super(type)
        this.age = 2
    }
}