JavaScript 中,内建对象的构造器函数(例如 Array、 String、 Object 和Function)都是可以通过其原型来进行扩展的
例子
- 比如扩展Array构造函数,添加一个功能 : 判断数组中是否存在
Array.prototype.inArray = function(needle) {
for (var i = 0, len = this.length; i < len; i++) {
if (this[i] === needle) {
return true;
}
}
return false;
};
- 比如给字符串添加一个反转字符串的功能
//2 .扩展字符串
String.prototype.reverse = function (str) {
// 下边这种写法是错误的 :
// return Array.prototype.reverse.call(str) ;
// 正确写法
return Array.prototype.reverse.call(str.split('')).join('') ;
}
var s1 = 'abc';
console.log(s1.reverse(s1)) //输出cba
对于扩展原型的讨论
1
扩展原型时先检查该属性是否已经存在
if (typeof String.prototype.trim !=== 'function'){
String.prototype.trim = function () {
return this.replace(/^\s+|\s+&/g, '' );
};
}
2
原型陷阱
-
prototype.constructor 属性是不可靠的
当我们重写某对象的 prototype 时,需要重置相应的 constructor 属性
// 原因是 : 重写构造函数的prototype时,如果忘记指定constructor 则会找默认proto function Dog() { this.tail = true; } var benji = new Dog(); var rusty = new Dog() Dog.prototype.say = function(){ return 'Woof!'; }; // 对象可以使用 say() benji.say(); // 输出 Woof! // 覆盖原型 benji 和 rusty 依然有__proto__指向旧构造函数prototype Dog.prototype = { talk : function(){ return 'Woof111!'; } } benji.say(); // 输出 Woof! //只是 不能用新属性 // benji.talk(); 报错 // 之后创建的对象,__proto__ 指向新的 prototype var lucy = new Dog(); lucy.talk(); //输出 Woof111 // 但是constructor 已经不是 Dog() ,而是指向了 Object
重写原型时,获取对象属性用 this
function randomInt ( n,m){
return Math.floor(Math.random() * (m-n+1) + n)
}
Array.prototype.shuffle = function(){
// 原型中如果想用到实例对象的属性, 同this
var alen = this.length;
var i = alen;
while(i-- > 0){
// 随机一个[0,alen]之间整数 ,如果不等于当前坐标,交换
var j = randomInt(0,i);
if(i != j){
var temp = this[i] ;
this[i] = this[j]
this[j] = temp;
}
}
}
var arr = [2,3,4,5,6,7,8,9,12,14,16,17,22,66,345];
arr.shuffle();
console.log(arr.toString())