看完这篇文章,你将了解:
- 展开运算符在哪使用
- 解释型语言是什么
- 补充三种跨域 tricks
- 描述页面性能的时间点 (什么是 first paint, domready, onload)
- JS 的浮点数问题 (.2 + .4 !== .6 怎么办)
- 可迭代对象
- 用 Object.prototype.toString 检测对象类型
- instanceof 的用法与定义
展开运算符
根据 MDN ,在遇到以下情形时可以考虑展开运算符
- 函数传参
- 数组构造
- 数组或对象克隆
比如
// 函数传参
function myFunction(x, y, z) {}
var args = [0, 1, 2]
myFunction(...args) // 可用 apply 代替
var dataFields = [2000, 1, 1]
var d = new Date(...dateField) // 不可用 apply 代替
// 数组构造
var parts = ['a', 'b']
var lyrics = [...parts, 'c', 'd', 'e']
// 数组克隆
var arr = [1, 2, 3]
var arr2 = [...arr] // 可用 arr.slice() 代替
// 此时 arr2 与 arr 一样而 arr 不受影响(若 arr 不含引用类型成员)
// 对象克隆
var obj = {a: 1, b: 2}
var obj2 = {...obj} // 可用 JSON.parse(JSON.stringify()) 代替
// 此时 obj2 与 obj 一样而 obj 不受影响(若 obj 不含引用类型值)此外,还可以通过以下方式赋值
let [head, ...tail] = [1, 2, 3, 4]
console.log(head) // 1
console.log(tail) // [2, 3, 4]解释性语言
解释性语言是相对于编译型语言而言的。
先将程序编译成机器语言,然后再运行编译后的文件的就是编译型语言, 如 C++, 先生成 exe,再运行 exe 文件
边解释边运行程序的就是解释型语言,如 JavaScript,不借助中间文件
跨域补充
参考这篇文章, 除了 jsonp 外,还可以用以下方式跨域
衡量页面性能的四个时间点
- 白屏时间(first Paint Time)——用户从打开页面开始到页面开始有东西呈现为止
- 首屏时间——用户浏览器首屏内所有内容都呈现出来所花费的时间
- 用户可操作时间(dom Interactive)——用户可以进行正常的点击、输入等操作,默认可以统计 domready 时间,因为通常会在这时候绑定事件操作
- 总下载时间——页面所有资源都加载完成并呈现出来所花的时间,即页面 onload 的时间
时间顺序是:first paint → 首屏 → domready → onload
Javascript 的浮点数计算问题
.2 + .4 === .6 // false
.2 + .4 === .6000000000000001 // true解决方法是
// 如果是判断式,用 Number.EPSILON
Math.abs(.2 + .4 - .6) < Number.EPSILON
// 如果是计算式,用 toFixed()
(.2 + .4).toFixed(1) // .6注意:这里补充一下浮点数的 toFixed 方法与 toPrecision 方法的区别
- toFixed(n): 固定小数位数为 n,toPrecision(n): 固定有效位数为 n
- toFixed 返回小数,toPrecision 返回字符串
1.08.toFixed(1) // 1.1
1.08.toPrecision(1) // 1可迭代对象
根据 MDN ,可迭代对象是指:
一个实现了 @@iterator 方法的对象,该对象可以在原型链上找到 Symbol.iterator 属性
比如数组:

可迭代对象的特点是可以通过 for a of obj 遍历,并且 for a of obj 遍历的时候会调用 @@iterator 方法。该方法返回一个迭代器
根据标准,JS 内置的可迭代对象有以下几种:
// 1)数组
for(let x of ['a','b'])
console.log(x)
// 2)字符串
for(let x of "abc")
console.log(x)
// 3)Map
let map = new Map().set('a', 1).set('b', 2);
for (let pair of map) {
console.log(pair);
}
// 4)Set
let set = new Set().add('a').add('b');
for (let x of set) {
console.log(x);
}
// 5)arguments
function printArgs() {
for (let x of arguments) {
console.log(x);
}
}
printArgs('a', 'b');
// 6)Typed Arrays
// 7)Generators可以通过以下方法判断一个对象是否为可迭代对象
var arr = [1, 2, 3, 4]
// 能否用 for of 遍历
for (a of arr) {console.log(a)}
// 是否有 Symbol.iterator 方法
typeof a[Symbol.iterator]注意可迭代对象和迭代器是不同的,区别在于:
- 可迭代对象:实现了
@@iterator方法 - 迭代器:实现了
next方法
同时可迭代协议和迭代器协议也是不同的,区别在于:
- 可迭代协议:允许 JS 对象定制自己的迭代行为,比如定义在一个
for a of obj中什么样的值可以被遍历 - 迭代器协议:定义一个标准的方式来产生有限或无限序列的值,所有值完成遍历后返回默认值
Object.prototype.toString.call(obj) 对象类型检测
有一个问题,如何判断一个 js 对象是数组类型
Array.isArray // 对
instanceof // 对
typeof // 错
Object.prototype.toString // 对作为答案之一,今天知道了一个方法 Object.prototype.toString.call(obj)
根据 MDN
toString()can be used with every object and allows you to get its class. To use theObject.prototype.toString()with every object, you need to callFunction.prototype.call()orFunction.prototype.apply()on it, passing the object you want to inspect as the first parameter calledthisArg.
instanceof 的用法与定义
之前疑惑的一点是:
var arr = new Array(1, 2, 3, 4)
arr instanceof Array // true
arr instanceof Object // true
为什么 instanceof 允许与两个不同的值运算为 true?
IBM Developer 上的一篇文章解决了我的困惑
通常来讲,使用 instanceof 就是判断一个实例是否属于某种类型。例如:
// 判断 foo 是否是 Foo 类的实例 function Foo(){} var foo = new Foo(); console.log(foo instanceof Foo) //true另外,更重要的一点是 instanceof 可以在继承关系中用来判断一个实例是否属于它的父类型。例如:
// 判断 foo 是否是 Foo 类的实例 , 并且是否是其父类型的实例 function Aoo(){} function Foo(){} Foo.prototype = new Aoo(); //JavaScript 原型继承 var foo = new Foo(); console.log(foo instanceof Foo) //true console.log(foo instanceof Aoo) //trueJavaScipt instanceof 运算符代码 (ps: 这不就是链表查找么)
function instance_of(L, R) { //L 表示左表达式,R 表示右表达式 var O = R.prototype; // 取 R 的显示原型 L = L.__proto__; // 取 L 的隐式原型 while (true) { if (L === null) return false; if (O === L) // 这里重点:当 O 严格等于 L 时,返回 true return true; L = L.__proto__; } }
金句
- 展开运算符可以用于函数传参,构造数组,克隆对象
- document.domain, window.name, postMessage 可以跨域
- 衡量页面性能的四个指标依次是 first paint, 首屏, domready, onload
- toFixed 是固定小数位数, toPrecision 是固定有效位数
- 可迭代对象是指一个实现了 @@iterator 方法的对象,可以用 for of 遍历
- 可以用 Object.prototype.toString.call 方法检测一个对象种类
- instanceof 本质是定义在原型链上的链表查找
暂无评论