能在实例的 原型对象链 中找到该构造函数的prototype 属性所指向的 原型对象,就返回true 。即:
- // __proto__: 代表原型对象链
- instance.[__proto__...] === instance.constructor.prototype
-
- // return true
10. 代码的复用
当你发现任何代码开始写第二遍时,就要开始考虑如何复用。一般有以下的方式:
- 函数封装
- 继承
- 复制
extend
- 混入
mixin
- 借用
apply/call
11. 继承
在 JS 中,继承通常指的便是 原型链继承,也就是通过指定原型,并可以通过原型链继承原型上的属性或者方法。
- var inherit = (function(c,p){
- var F = function(){};
- return function(c,p){
- F.prototype = p.prototype;
- c.prototype = new F();
- c.uber = p.prototype;
- c.prototype.constructor = c;
- }
- })();
- 使用 ES6 的语法糖
class / extends
12. 类型转换
大家都知道 JS 中在使用运算符号或者对比符时,会自带隐式转换,规则如下:
- -、*、/、% :一律转换成数值后计算
-
+:
- 数字 + 字符串 = 字符串, 运算顺序是从左到右
- 数字 + 对象,, 优先调用对象的
valueOf -> toString
- 数字 +
boolean/null = 数字
- 数字 +
undefined == NaN
[1].toString() === '1'
{}.toString() === '[object object]'
NaN !== NaN 、+undefined === NaN
13. 类型判断
判断 Target 的类型,单单用 typeof 并无法完全满足,这其实并不是 bug,本质原因是 JS 的万物皆对象的理论。因此要真正完美判断时,我们需要区分对待:
- 基本类型(
null ): 使用 String(null)
- 基本类型(
string / number / boolean / undefined ) + function : 直接使用 typeof 即可
- 其余引用类型(
Array / Date / RegExp Error ): 调用toString 后根据[object XXX] 进行判断
很稳的判断封装:
- let class2type = {}
- 'Array Date RegExp Object Error'.split(' ').forEach(e => class2type[ '[object ' + e + ']' ] = e.toLowerCase())
-
- function type(obj) {
- if (obj == null) return String(obj)
- return typeof obj === 'object' ? class2type[ Object.prototype.toString.call(obj) ] || 'object' : typeof obj
- }
14. 模块化
模块化开发在现代开发中已是必不可少的一部分,它大大提高了项目的可维护、可拓展和可协作性。通常,我们 在浏览器中使用 ES6 的模块化支持,在 Node 中使用 commonjs 的模块化支持。
|