持续补充
1. 浏览器 DOM事件机制?
- addeventlistener(event, callback)
- 事件冒泡: 事件委托的原理 <ul><li>..... 事件绑定到ul即可
- 事件捕获
- e.eventPropagation() 阻止 冒泡向上传播
- e.preventDefault() 阻止 自身 事件
2. JSBridge 如何通信?
- url schema: Native拦截 Webview请求。
- native api: 类似注入http://window.xxx下,让JS调用。
3. 'a' 和 String('a') 和 new String('a')?
- new String('a') => 本质是对象object了,引用类型,值保存在堆内存 heap 中。
- 'a' string 类型,基本类型的值保存在 stack 栈 内存中。
- String('a') 同 2
4. js浮点数运算不精确 如何解决?
- 问题: JS 浮点数精度 计算有问题
- 原因: JS 类型只有Number, 只有64位形式储存, 所以1 和 1.0 是一样的,JS利用 64位浮点数存储,浮点数的二进制是表示是无穷的,所以多出位数会被截掉。
- 就是说 10进制的 转 2进制后,因为二进制表示会有舍弃某位置,再转换回来 10进制,就会出问题。
- 解决1: 转成整数 后 再运算,再转小数。例如: (0.1 * 10 + 0.2 * 10) / 10
- 解决2: 还有些包支持。npm引用去吧。
JavaScript 浮点数陷阱及解法
5. DOM 操作 基础
创建 DOM节点 / 文本
- document.createElement('div')
- document.createTextNode('我只是个文本')
获取 / 查询 DOM节点
- document.getElementById
- document.getElementsByClassName 返回所有 数组格式
- document.getElementsByTagName('div') 返回所有 数组格式
- document.querySelector(".classname") 获取第一个class名为 classname
- document.querySelectorAll("div.note, div.alert") 获取所有 class为note 或 alert的 div元素
DOM 节点下的 属性 set/ get, 有没有, 移除
- document.getElementById('dom-id').getAttribute('class')
- document.getElementById('dom-id').setAttribute('class', 'add-attribute')
- hasAttribute('class')
- removeAttribute('class')
DOM 变更 增 删 改
- dom.appendChild(el)
- dom.removeChild(el)
- dom.replaceChild(el1, el2)
6. DOM 节点类型
DOM的节点类型
7. let const var
- let 类似 var, 但是 let const 有变量声明提升,但不会给他们分配内存空间,所以也相当于不提升了。
- const: 没有变量提升,不许重复声明,重复赋值也不行。
let 和 const 有变量声明提升, 但不会因为声明而分配内存区域,所以报错。
console.log(a) // undefined 因为变量提升,提前声明了
var a = '1'
console.log(b) // Uncaught ReferenceError: b is not defined 报错,let无声明提升
let b = '1'
let 和 const 不能重复声明
let a = 1
let a = 2 // 报错
var b = 1
var b = 2 // 不会报错
8. 前端存储方式
- cookies: 4kb, 每个domain有规定20个cookies
- (web存储) local storage: 5M大小 持久保存
- (web存储) session storage: 当前会话级别存储
- IndexedDB: 50M + 支持离线化存储 兼容性高些
- IndexedDB 是异步读取 localstorage同步读取
9. 判断数组
- Array.isArray() es6 新判断
- Object.prototype.toString.call(xx) === '[object Array]'
10. Map / Set 和 Object区别
1. Map类似Object
但是Object key值只能是string类型, Map key 值可以是Object, Boolean都行
2. Set类似Array, 但是是返回的是不重复的数组
const key1 = { a: 1 }
const key2 = false
const map = new Map()
map.set(key1, 111)
map.set(key2, 222)
map.get(key1)
key1 = null // 我们清空了该引用类型, 但是
map.keys() // 我们还是可以从 这种方式直接获取到 key1的值
/*
Map: {
[[Entries]]: {
0: {Object => 111},
1: {false => 222}
}
}
*/
问题: 因为key值可以是object引用类型, 意味着会保存在堆内存中,
即使key1 = null 释放,在mao里的还是会存在的
这样会引起内存泄露哦
new Set([1, 2, 1,1,1,1])
/*
Set: {
[[Entries]]: {
0: 1
1: 2
}
}
11. WeakMap / WeakSet
- 只能用 key值为引用类型的, 当key在内存空间中被清除了,WeakMap 里对应的也会消失。
- 但是上描述的方式,map不会
const weakmap = new WeakMap()
const key1 = { a: 1 }
weakmap.set(key1, 1) // key值只能是 引用类型
weakmap.set('key2', 'key2') // 报错,只能应用类型
key1 = null // key作为引用清空了, 随之 weakmap 也没了该值
- WeakSet 只能用 对象作为值
const weakset = new WeakSet()
var a = { name: 'a' }
var b = { name: 'b' }
weakset.add(a)
weakset.add(b)
console.log(weakset.has(a)) // 检查是否有a
a = null // 则weakset里a也会跟着消失
console.log(weakset) // 此时只有一个值了 b
总结: 必须是引用类型,无论是WeakMap 中 key 还是 WeakSet中的值,都必须是引用类型。
刚该引用类型清空的时候,随之WeakSet / WeakMap里也会被清空。
好处: key值或值必须是引用类型,直接回收掉,不会引起内存泄露。
不好: 无法遍历。必须是对象。