在JavaScript权威指南中,对prototype的定义如下:the prototype object holds methods and other properties that should be shared by each instance.
在JavaScript中,有一个所有对象都有的属性,即Prototype。Prototype自身也是对象,它也有自己的prototype,这样就形成了一个prototype链,该链的终止在Object,因为Object的prototype属性是null,如果在这次寻根溯源中没有找到,就会返回undefined。prototype的作用并不是往结果对象上添加东西,而是保证在上面的东西能被找到,如下代码
function MyObject(){}
MyObject.prototype.x = 1;
var obj = new MyObject();
alert("obj.x="+obj.x);
结果:obj.x = 1
同时,在这种prototype链中,如果在被依赖的对象中加入新的prototype属性,会立即体现在依赖的对象中,如下代码:
function MyObject(){}
MyObject.prototype.x = 1
var obj1 = new MyObject()
obj1.x // 1
MyObject.prototype.y = 2
obj1.y // 2
新建的对象并没有x属性,这时它就会自动到创建这个对象的构造函数MyObject的prototype中去找。于是找到了1。下面的代码是修改对象的prototype属性:
function MyObject(){ }
MyObject.prototype.x = 1;
var obj = new MyObject();
alert("obj.x="+obj.x);
MyObject.prototype.x = 2;
alert("obj.x="+obj.x);
结果:obj.x = 1; obj.x = 2; 更加说明新创建的对象找的其实是MyObject上的x。
function MyObject(){}
MyObject.prototype.x = 1;
var obj = new MyObject();
obj.x = 2;
alert(MyObject.prototype.x); //弹出 1
MyObject.prototype.x = 3;
alert(obj.x);//弹出2
delete obj.x;
alert(obj.x)//弹出3
重结果可以看出,当对象有自己的同名属性后就不会到构造函数里的prototype去找了。之后MyObject的x属性的改变都影响不到新创建对象了。
function MyObject1(){}
MyObject1.prototype.x = 1;
function MyObject2(){}
MyObject2.prototype = new MyObject1();
var obj = new MyObject2();
alert(obj.x);
输出结果是 : 1。
同时我们甚至可以直接在Function对象上加一个prototype的方法,这样在后面新创建出来的方法中就有了这个方法,代码如下:
Function.prototype.newFunction = function(){return "this is a new function added to Function object" }
function TestFunction(){}
var test = TestFunction.newFunction()
console.log(test) // this is a new function added to Function object
下面有一段更加tricky的代码:
Function.prototype.methodRegistration = function (name, func) {
this.prototype[name] = func;
return this;
}
这段代码的意思是,向Function对象中添加一个方法,名叫methodRegistration,顾名思义是一个用于注册方法的方法。方法要求传入一个名字和方法体,方法体中的this.prototype[name] = func;的意思是调用这个方法的对象,在下面这段代码中即是Number对象:
Number.methodRegistration("numberCeilingOrFloor", function() {
return Math[this < 0 ? "ceiling" : "floor"](this);
}
);
这样就向Number对象中注册了一个numberCeilingOrFloor方法,该方法的意图是提取出数字中的整数部分,如果数字大于0,就向上提取(五入),如果小于0就舍去。使用的代码为:
var test = (10/3).numberCeilingOrFloor();
结果为:
console.log(test) // 3