js原生原型

原生原型

原生构造函数有自己的 .prototype 对象,如 Array.prototype、String.prototype 等。

这些对象包含其对应子类型所特有的行为特征。

例如,将字符串值封装为字符串对象之后,就能访问 String.prototype 中定义的方法。

  • String#indexOf(..)
  • String#charAt(..)
  • String#substr(..)、String#substring(..) 和 String#slice(..)
  • String#toUpperCase() 和 String#toLowerCase()
  • String#trim()

以上方法并不改变原字符串的值,而是返回一个新字符串。

借助原型代理(prototype delegatio),所有字符串都可以访问这些方法:

js原生原型

其他构造函数的原型包含它们各自类型所特有的行为特征,比如 Number#tofixed(..)(将 数字转换为指定长度的整数字符串)和 Array#concat(..)(合并数组)。所有的函数都可以 调用 Function.prototype 中的 apply(..)、call(..) 和 bind(..)。

然而,有些原生原型(native prototype)并非普通对象那么简单:

typeof Function.prototype; // "function"

Function.prototype(); // 空函数!

RegExp.prototype.toString(); // "/(?:)/"——空正则表达式

"abc".match( RegExp.prototype ); // [""]

更糟糕的是,我们甚至可以修改它们(而不仅仅是添加属性):

Array.isArray( Array.prototype ); // true

Array.prototype.push( 1, 2, 3 ); // 3

Array.prototype; // [1,2,3]

// 需要将Array.prototype设置回空,否则会导致问题!

Array.prototype.length = 0;

这里,Function.prototype 是一个函数,RegExp.prototype 是一个正则表达式,而 Array. prototype 是一个数组。是不是很有意思?

将原型作为默认值

Function.prototype 是一个空函数,RegExp.prototype 是一个“空”的正则表达式(无 任何匹配),而 Array.prototype 是一个空数组。对未赋值的变量来说,它们是很好的默 认值。

js原生原型

这种方法的一个好处是 .prototypes 已被创建并且仅创建一次。相反,如果将 []、 function(){} 和 /(?:)/ 作为默认值,则每次调用 isThisCool(..) 时它们都会被创建一次 (具体创建与否取决于 JavaScript 引擎,稍后它们可能会被垃圾回收),这样无疑会造成内 存和 CPU 资源的浪费。

另外需要注意的一点是,如果默认值随后会被更改,那就不要使用 Array.prototype。上例 中的 vals 是作为只读变量来使用,更改 vals 实际上就是更改 Array.prototype,而这样会 导致前面提到过的一系列问题!


分享到:


相關文章: