Skip to main content

js

1. ('b' + 'a' + +'a' + 'a').toLowerCase()

;('b' + 'a' + +'a' + 'a').toLowerCase() // 输出banana

// 关于 NaN
// 1. 任何 数字 和 NaN 计算都是 NaN
// 2. 任何数字和 undefined 运算,得到 NaN;

2. 计算转换问题

[]+{}//'[object Object]'
[]+[]//''
{}+[]//0 //+[] //[].toString() == ""; +" " == 0

只有以下两种形式

  1. number + number
  2. string+string

[ ]+{ } []会通过隐式转换规则,调用 toString 方法转换为 "" ,同理{}转换为[object Object], 相加得出字符串拼接结果 [object Object]

{} + [] js 解析器 会将{} 看作代码块,然后执行 +[] 得到 0

3. (!+[]+[]+![]).length//9

;(!+[] + [] + ![]).length //9

输出 9

  1. 第一步计算+[] 得到 0
  2. 第二步计算!+[]得到 true
  3. 第三步计算!+[] + [] 即 true+ [] = true+'' 得到字符串 'true'
  4. 第四步计算!+[] + [] + ![] = 'true'+'false' 得到 'truefalse'
  5. 最后得到 9

4. 变量提升, js 的预编译

//6.// 函数
function fn(a) {
console.log(a) //根据AO对象中的数据第一个打印的是:fn()
// 变量声明+变量赋值(只提升变量声明,不提升变量赋值)
var a = 123 // 执行到这时,由于变量赋值是不提升的,所以函数被123覆盖了
console.log(a) // 123
// 函数声明
function a() {} // 这里被提升上去了,可以忽略
console.log(a) // 123
// 函数表达式
var b = function () {}
console.log(b) // 根据AO对象中的数据:fn()
// 函数
function d() {}
}
//调用函数
fn(1)

5. 其他

0 == 0 //true
0 == [] //true
0 == [] //false
typeof NaN //number
99999999999//100000000000
0.1+0.2==0.3//false 精度丢失
Math.max()//-Infinity 负无穷
Math.min()//Infinity 正无穷
[] == false //true
0==false //true
undefined == false //true
NaN == false //true
== false //true 包括多空格
null == false //true

6.onload 和 ready

  1. onload()

执行时机:等待页面中的所有资源(包括图片、视频等资源)css js html 都加载完成后,才会执行。

而且在 js 中文件中只有一个 onload 事件。

  1. ready()

表示文档结构已经加载完成(不包含图片等非文字媒体文件)

执行时机:等待页面 Dom 树加载完成后,就开始执行。

在 js 文件中可以出现多个 ready(),并且按照顺序执行。

js 对象的 set 和 get 用法

对象的 set get 是 es5 的中对象的特性,使用示例:

  1. 在初始化对象的时候这样使用
var obj = {
a: 1,
b: 2,
set c(x) {
console.log('c 被赋值:', x)
c = x
},
get c() {
console.log('c 被取出: ', c)
return c
},
}

obj.c = 3 //c 被赋值: 3
obj.c //c 被取出: 3
  1. 对象初始化之后可以这样添加属性
var obj = {
a: 1,
b: 2,
}

obj.__defineGetter__('c', function () {
return c
})
obj.__defineSetter__('c', function (x) {
c = x
})

defineGetter 方法可以将一个函数绑定在当前对象的指定属性上,当那个属性的值被读取时,你所绑定的函数就会被调用。 该特性是非标准的,请尽量不要在生产环境中使用它!

  1. 使用 defineProperty
Object.defineProperty(obj, c, {
set: function (x) {
console.log('c 被赋值:', x)
c = x
},
get: function () {
console.log('c 被取出:', c)
return c
},
})

obj.c = 3 //c 被赋值: 3
obj.c //c 被取出: 3

对象的遍历

  1. for..in..遍历

    • 遍历自身及原型链上所有可枚举的属性
    • 并不需要将原型链上的属性也遍历出来
    • 还进行了原型链查找,当只需要遍历对象自身的时候,性能上会收到一定影响。
    for (let n in qiu) {
    // 判断是否实例自身拥有的属性
    if (qiu.hasOwnProperty(n)) {
    console.log(n)
    }
    }
  2. Object.keys 遍历

    返回一个数组,包括对象自身的(不含继承的)所有可枚举属性

    const searchObj = {
    title: 'javascript',
    author: 'Nicolas',
    publishing: "O'RELLY",
    language: 'cn',
    }
    let searchStr = Object.keys(searchObj)
    .map((item) => `${item}=${searchObj[item]}`)
    .join('&')
    let url = `localhost:8080/api/test?${searchStr}`
  3. Object.getOwnPropertyNames 遍历

    返回一个数组,包含对象自身(不含继承)的所有属性名

    与 Object.keys 的区别在于 Object.getOwnPropertyNames 会把不可枚举的属性也返回。除此之外,与 Object.keys 的表现一致

    var Person = function ({ name = 'none', age = 18, height = 170 } = {}) {
    this.name = name
    this.age = age
    this.height = height
    }

    Person.prototype = {
    type: 'Animal',
    }

    var qiu = new Person()

    // 将height属性设置为 不可枚举
    Object.defineProperty(qiu, 'height', {
    enumerable: false,
    })

    var keys = Object.getOwnPropertyNames(qiu)
    console.log(keys)
    // output: ['name', 'age', 'height']
  4. 说好的 for..of..,为什么无效

    在 ES6 中新增了迭代器与 for..of..的循环语法,在数组遍历、Set、Map 的遍历上,十分方便。然而当我应用在对象(特指 Object 的实例 )上时(如下代码),浏览器给我抛了一个异常:Uncaught TypeError: searchObj is not iterable。

    const searchObj = {
    title: 'javascript',
    author: 'Nicolas',
    publishing: "O'RELLY",
    language: 'cn',
    }

    for (let n of searchObj) {
    console.log(n)
    }
    // Uncaught TypeError: searchObj is not iterable

    在 ES6 中,对象默认下并不是可迭代对象,表现为其没有[Symbol.iterator]属性,可以通过以下代码对比

    const searchObj = {
    title: 'javascript',
    author: 'Nicolas',
    }
    const bookList = ['javascript', 'java', 'c++']
    const nameSet = new Set(['Peter', 'Anna', 'Sue'])

    console.log(searchObj[Symbol.iterator]) // undefined
    console.log(bookList[Symbol.iterator]) // function values(){[native code]}
    console.log(nameSet[Symbol.iterator]) // function values(){[native code]}

    // 注,Set、Map、Array的[Symbol.iterator]都是其原型对象上的方法,而非实例上的,这点需要注意

    而 for..of..循环,实际上是依次将迭代器(或任何可迭代的对象,如生成器函数)的值赋予指定变量并进行循环的语法,当对象没有默认迭代器的时候,当然不可以进行循环,而通过给对象增加一个默认迭代器,即[Symbol.iterator]属性,就可以实现,如下代码:

    Object.prototype[Symbol.iterator] = function* keys() {
    for (let n of Object.keys(this)) {
    // 此处使用Object.keys获取可枚举的所有属性
    yield n
    }
    }

    const searchObj = {
    title: 'javascript',
    author: 'Nicolas',
    publishing: "O'RELLY",
    language: 'cn',
    }

    for (let key of searchObj) {
    console.log(key)
    }
    // output: title author publishing language

null 和 undefined

  1. 区别

    • null 和 undefined 都代表没有;
    • typeof null -->"object";空对象指针;
    • null 表示现在没有,但是以后可能会有;undefined 表示现在没有,以后也没有;
  2. 常见的 null 的情况;

    • 通过 ID 获取元素,如果 ID 名字不存在,那么返回 null;
    • 通过正则进行捕获时,如果没有获取到内容,那个结果是 null;
    • 在清空对象,销毁堆内存是,给对象赋值为 null
  3. undefined 情况

    • 当获取对象属性名对应的属性值时,如果属性名不存在,那么返回值是 undefined.
    • 函数的形参如果没有实参赋值,在函数中默认存储 undefined
    • 如果函数没有 return,那么函数的返回值是 undefined.
    • 如果变量只声明,没有赋值,那么默认存储是 undefined.