其他

coderljw 2024-10-13 JS 基础
  • JS 基础
  • JS
大约 4 分钟

# 1. for in

  • for in 遍历除 symbol 类型外的可枚举属性,会进行原型链查找。
function Foo(name, age) {
  this.name = name
  this.age = age
  this[Symbol(7)] = 7
}
Foo.prototype.wife = '姜姒'
const bar = new Foo('徐扶墙', 17)

for (const key in bar) console.log(key, bar[key]) // 依次打印:'name' '徐扶墙' -> 'age' 17 -> 'wife' '姜姒'

const ary = [1, 2, 3]
for (const index in ary) console.log(index, ary[index]) // 依次打印:'0' 1 -> '1' 2 -> '2' 3

const str = 'love'
for (const index in str) console.log(index, str[index]) // 依次打印:'0' 'l' -> '1' 'o' -> '2' 'v' -> '3' 'e'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 2. for of

  • for of 遍历可迭代对象(通过 Symbol.iterator 定义迭代数据)。

    function Foo(name, age) {
      this.name = name
      this.age = age
    }
    Foo.prototype.wife = '姜姒'
    const bar = new Foo('徐扶墙', 17)
    
    for (const [key, value] of Object.entries(bar)) console.log(key, value) // 依次打印:'name' '徐扶墙' -> 'age' 17
    
    for (const value of [1, 2, 3]) console.log(value) // 依次打印:1 -> 2 -> 3
    
    for (const value of 'love') console.log(value) // 依次打印:'l' -> 'o' -> 'v' -> 'e'
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
  • 与 for in 区别。

    const ary = [1, 2, 3]
    ary.neo = 'Neo'
    Array.prototype.trinity = 'Trinity'
    
    for (const index in ary) console.log(index) // 依次打印:'0' -> '1' -> '2' -> 'neo' -> 'trinity'
    
    for (const value of ary) console.log(value) // 依次打印:1 -> 2 -> 3
    
    1
    2
    3
    4
    5
    6
    7
  • 与 forEach、map 等 ES6 函数区别。

    const ary = [3, 2, 1]
    function promise(num) {
      return new Promise((resolve, reject) => {
        setTimeout(() => resolve(num), 1000 * num)
      })
    }
    
    function foo() {
      ary.forEach(async value => console.log(await promise(value)))
    }
    
    async function bar() {
      for (const value of ary) console.log(await promise(value))
    }
    
    foo() // 总耗时约3s,依次打印:1 -> 2 -> 3
    bar() // 总耗时约6s,依次打印:3 -> 2 -> 1
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
  • 自定义迭代器

    const foo = {
      name: '徐扶墙',
      age: 17,
      [Symbol.iterator]() {
        const entries = Object.entries(this)
        return {
          i: -1,
          next() {
            this.i++
            if (this.i < entries.length) return { value: entries[this.i], done: false }
            return { value: undefined, done: true }
          },
        }
      },
    }
    
    for (const [key, value] of foo) console.log(key, value) // 依次打印:'name' '徐扶墙' -> 'age' 17
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17

# 3. void

  • void 任何值都会返回 undefined,在项目中推荐使用 void 0 代替 undefined(还有字数优势哟!)。

    在 JS 中 undefined 不属于关键字,因此 undefined 可做变量;低版本浏览器中可以改变 undefined 的值,高版本浏览器已经杜绝此现象。

undefined === void 0 // => true
1

# 4. delete

const foo = {
  name: '徐扶墙',
  age: 17,
}
const ary = [1, 2, 3]
const str = 'clearlove7'

// 删除属性存在
delete foo.name // => true
// 删除属性不存在
delete foo.wife // => true

// 删除数组元素,删除项用 empty 占位,获取为 undefined,不能遍历,不会改变数组长度
delete ary[1] // => true

// 不能删除已声明变量,应使用 null 回收
delete str // => false
delete bar // => true

// 不声明变量,属性会定义在 window 下,可以删除
num = 777
console.log(num) // => 777
delete num // => true
console.log(num) // => num is not defined
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 5. with(object) { }

  • 会扩展一个语句的作用域链,模版引擎编译常用语法,但性能不好(慎用)。

  • 在内部中由于 var 声明没有块级作用域,将会声明在 object 下。

const foo = {
  name: '徐扶墙',
  age: 17,
  wife: '姜姒',
  rank: 2,
}

with (foo) {
  var wife = '裴南苇'
  let name = '徐凤年'
  const age = 18
  console.log(rank) // => 2
  console.log(foo) // => {name: '徐扶墙', age: 17, wife: '裴南苇', rank: 2}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 6. eval(string)

  • 将传入的字符串当做 JavaScript 代码进行执行(慎用)。

  • 通过 eval() 定义的任何变量和函数都不会被提升,这是因为在解析代码的时候,它们是被包含在一个字符串中的,它们只是在 eval() 执行的时候才会被创建。

  • 使用 eval() 执行一批语句时,将返回 “最后执行到的、有返回值的” 那条语句的值。

eval("console.log('执行代码')") // => "执行代码"

eval("1 + 2; const x = 5; ; function foo() {}") // => 3

eval("1 + 2; const x = 5; ; function foo() {}; 7") // => 7
1
2
3
4
5

# 7. label

  • 为程序定义位置,可以使用 continue/break 跳到该位置。
const ary = []

jack: for (let i = 1; i < 20; i++) {
  pony: for (let j = 1; j < 20; j++) {
    if (j % 2 !== 0) continue pony

    if (ary.length < 10) {
      ary.push(i ** j)
      break pony
    }

    break jack
  }
}
console.log(ary) // => [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 8. Base64

  • 每一个 Base64 字符实际上代表着 6 比特位。因此,3 字节(一字节是 8 比特,3 字节也就是 24 比特)的字符串/二进制文件可以转换成 4 个 Base64 字符(4x6 = 24 比特)。

  • 原来的 3 个字节编码后将成为 4 个字节,这意味着 Base64 格式的字符串或文件的尺寸约是原始尺寸的 133%(增加了大约 33%)。如果编码的数据很少,增加的比例可能会更高。

// 编码
btoa('clearlove7') // => 'Y2xlYXJsb3ZlNw=='

// 解码
atob('Y2xlYXJsb3ZlNw==') // => 'clearlove7'
1
2
3
4
5
以父之名
周杰伦.mp3