本文汇总了 JavaScript 中实用且高效的原生 API 与编程技巧。内容涵盖字符串解析、位运算交换变量、日期格式化与时间戳获取、URI 编码解码、数值精度控制以及基于 Object.prototype.toString 的精准类型检测。同时详细解析了 Array 原型链上各类方法的特性、返回值及迭代函数的执行逻辑,帮助开发者写出更简洁高效的代码。
本文直接切入主题,整理一系列在 JavaScript 开发中实用且高效的 API 与技巧。
字符串解析与对象转换
字符串对象解析
通常我们知道 JavaScript 对象可以序列化为 JSON 字符串,JSON 字符串也能解析回对象。但当遇到一个既非标准 JSON 也非标准对象的字符串时,直接转换会十分困难。此时,eval 函数便派上了用场。
var obj = "{a:1,b:2}"; // 看起来像对象的字符串
eval("("+ obj +")") // {a: 1, b: 2}
利用 eval 执行字符串表达式,可以将形似对象的字符串转换为真正的对象。为了避免 eval 将包含花括号 {} 的字符串误判为代码块语句,建议在字符串外层包裹圆括号 (),强制其作为表达式进行解析。
位运算技巧
按位与运算 (&)
判断一个整数是否为 2 的 n 次幂,可以通过将其与自身减 1 的结果进行按位与运算来实现。
var number = 4
(number & number -1) === 0 // true
按位异或运算 (^)
无需引入第三个临时变量,即可利用按位异或运算交换两个变量的值。
var a = 4,b = 3
a = a ^ b // 7
b = a ^ b // 4
a = b ^ a // 3
日期格式化与时间戳处理
Date 对象格式化
若需获取特定格式的时间字符串,无需再手动调用 getFullYear、getMonth 等方法拼接年月日时分秒,通过简单几步即可完成格式化。
var temp = new Date();
var regex = /\//g;
(temp.toLocaleDateString() + ' ' + temp.toLocaleTimeString().slice(2)).replace(regex,'-');
// "2015-5-7 9:04:10"
若需将格式化后的时间字符串转换回 Date 对象,可直接利用 Date 构造函数进行实例化。
new Date("2015-5-7 9:04:10");
// Thu May 07 2015 09:04:10 GMT+0800 (CST)
若需将标准 Date 对象转换为 Unix 时间戳,调用 valueOf 方法即可快速获得。
(new Date).valueOf();
// 1431004132641
许多开发者还分享了一种更快捷获取时间戳的方式。
一元加运算符 (+)
一元加运算符
一元加运算符可快速将表示数字的字符串转换为数值类型,例如将字符串 "23" 转为数字 23。
var number = "23"
typeof number // string
typeof +number // number
此外,该运算符也可用于将 Date 对象转换为对应的时间戳。
new Date // Tue May 12 2015 22:21:33 GMT+0800 (CST)
+new Date // 1431440459887
URI 编码与解码
URI 编码与转义
当需要将 URL 作为参数在路由中传递时,需先对其进行编码处理。
var url = encodeURIComponent('http://segmentfault.com/questions/newest')
// "http%3A%2F%2Fsegmentfault.com%2Fquestions%2Fnewest"
接收端则需进行反向解码,还原原始 URL。
decodeURIComponent(url)
// "http://segmentfault.com/questions/newest"
数值类型与精度控制
Number 类型处理
若需保留小数点后指定位数,无需再进行复杂的字符串截取操作,直接使用 toFixed 方法即可。
number.toFixed() // "12346"
number.toFixed(3) // "12345.679"
number.toFixed(6) // "12345.678900"
该方法接收一个参数,范围在 0 到 20 之间,若不指定参数,默认保留 0 位小数。
精准类型检测机制
类型检测机制
typeof 是最常用的类型检测手段。
typeof 3 // "number"
typeof "333" // "string"
typeof false // "boolean"
对于基本数据类型,typeof 表现良好;但面对引用数据类型时,其局限性便显现出来。
typeof new Date() // "object"
typeof [] // "object"
typeof {} // "object"
typeof null // "object"
前三个还能忍,null居然也返回object,你是在逗我吗!!!(ps:其实这是JavaScript的bug 人艰不拆 ꒰・◡・๑꒱ )
此时,开发者通常会转而使用 instanceof 运算符。
toString instanceof Function
// true
(new Date) instanceof Date
// true
[] instanceof Object
// true
[] instanceof Array
// true
通过观察可以发现,[] 和 {} 使用 typeof 检测均返回 object。虽然我们知道数组也是对象,但我们需要一种更精确的类型判断方法。利用 Object.prototype.toString() 可以实现这一目标。为了确保每个对象都能正确检测,需使用 Function.prototype.call 或 Function.prototype.apply 来调用该方法。
var toString = Object.prototype.toString;
toString.call(new Date) // "[object Date]"
toString.call(new Array) // "[object Array]"
toString.call(new Object) // "[object Object]"
toString.call(new Number) // "[object Number]"
toString.call(new String) // "[object String]"
toString.call(new Boolean) // "[object Boolean]"
需要注意的是,toString 方法极有可能被重写,因此建议直接调用 Object.prototype.toString() 以确保准确性。
继承模式实现
继承实现
参考官方提供的示例代码。
//Shape - superclass
function Shape() {
this.x = 0;
this.y = 0;
}
Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
console.info("Shape moved.");
};
// Rectangle - subclass
function Rectangle() {
Shape.call(this); //call super constructor.
}
Rectangle.prototype = Object.create(Shape.prototype);
var rect = new Rectangle();
rect instanceof Rectangle //true.
rect instanceof Shape //true.
rect.move(1, 1); //Outputs, "Shape moved."
通过 call 方法获取父类初始化的属性和方法,再通过 Object.create 方法获取原型对象上的属性和方法,从而实现继承。
数组迭代与方法特性
数组迭代
ES5 引入了多个迭代函数,如 map、filter、some、every、reduce 等。
Array 原型方法详解
具体 API 说明可参考 Mozilla 开发者文档。此处简要提及:join、pop、push、reverse、shift、sort、splice、unshift 这些方法会直接修改原数组。
concat、indexOf、lastIndexOf、slice、toString 这些方法不会修改原数组。
map、filter、some、every、reduce、forEach 等迭代方法也不会修改原数组。
使用这些方法时需注意以下几点:
1. shift 和 pop 方法会返回被删除的元素。2. splice 方法会返回由被删除元素组成的数组,若无删除则返回空数组。3. push 方法会返回新数组的长度。4. some 方法在回调函数返回 true 时停止遍历。5. every 方法在回调函数返回 false 时停止遍历。6. 上述迭代方法最后可追加一个 thisArg 参数,用于指定回调函数执行时的 this 值。
以上即为本文介绍的全部内容,希望这些技巧能对读者有所帮助。