var arr = [, , , ];if (Array.prototype.indexOf) {alert("你的浏览器支持indexOf方法。");} else {alert("你的浏览器不支持indexOf方法。");}if (!Array.prototype.indexOf) {Array.prototype.indexOf = function(item) {for (var i = ; i < this.length; i++) {if(this[i]==item){return i;}}return -;}}alert(arr.indexOf());alert(arr.indexOf()); 当然这个方法是很垃圾的。在这里具体的实现 我就不献丑了,提供一个百度上copy的版本:if (!Array.prototype.indexOf){Array.prototype.indexOf = function(elt /*, from*/){var len = this.length >>> ;var from = Number(arguments[]) || ;from = (from < )? Math.ceil(from): Math.floor(from);if (from < )from += len;for (; from < len; from++){if (from in this &&this[from] === elt)return from;}return -;};} 2、继承——call和apply方法public class MyList<E> extends ArrayList<E>{public void myAdd(E e){super.add(e);System.out.println("Add:"+e);}} 但是js中没有继承的概念啊,我们可以用call和apply来解决这样的问题。var myObject = function(){}myObject.prototype.add = function(){Array.prototype.push.call(this,arguments);//输出argumentsfor(var i=;i<arguments.length;i++){console.log("Add:"+arguments[i]);}}var obj = new myObject();obj.add(,,); 这里可以看到:虽然用高级语言的继承方式实现了myAdd方法,但是现在myAdd方法只能传一个参数,如果要传多个参数,则需要再写一个public void myAdd(E[] e)方法,甚至是public void myAdd(List<E> e)方法。而JS用一个方法就可以搞定,用arguments对象表示输入的所有参数,这是高级语言难以做到的。var Obj = function(name){this.name = name;}Obj.prototype.getName = function(){return this.name;}var obj1 =new Obj("zou");var obj2 = {name:"andy"};var name = obj1.getName.call(obj2);alert(name); 参考是:var name = "goo";alert(obj1.getName.call(null)); (在严格模式下,由于全局对象是null,故会抛出异常:Uncaught TypeError: Cannot read property "name" of null)3、Object.defineProperty
function myobj(){}Object.defineProperty(myobj.prototype,"length",{get:function(){return this.length_; //这里不能是length。},set:function(value){return this.length_=value;}}); 注释的地方不能是length,否则会无限递归。Object.defineProperty(myobj.prototype,"length",{get:function(){return this.length_; //这里不能是length。}, /*set:function(value){return this.length_=value;}*/});myobj.length = 3; 这个代码会抛出异常:Uncaught TypeError: Cannot set property length of #<myobj> which has only a getter。Object.defineProperty(myobj.prototype,"length",{writable:false});writable:false不能与get set共存,否则会抛出Type Error。Object.defineProperty(myobj.prototype,"length",{configurable:false});var obj = new myobj();delete obj.length; value:指定该对象的固定值。value:10,表示这个对象初始值为10.Object.defineProperty(myobj.prototype,"length",{writable:false,value:"10"});var obj = new myobj();obj.length = 100; 可以用getOwnPropertyDescriptor来获取并修改这些值,比如说,现在我的length属性是只读的。Object.defineProperty(myobj.prototype,"length",{value:,writable:false,});var descriptor = Object.getOwnPropertyDescriptor(myobj.prototype, "length");descriptor.writable = true;Object.defineProperty(myobj.prototype,"length",descriptor); Uncaught TypeError: Cannot redefine property: length这是因为configurable的默认值是false,在调用了defineProperty之后,configurable就具有false属性,这样就不能逆转了。以后就不能改了。Object.defineProperty(myobj.prototype,"length",{value:,writable:false,configurable:true});var descriptor = Object.getOwnPropertyDescriptor(myobj.prototype, "length");descriptor.writable = true;Object.defineProperty(myobj.prototype,"length",descriptor);myobj.prototype.length = ;var obj = new myobj();alert(obj.length); 可以加上一句descriptor.configurable = false;
看见没,这个configurable是true,而setter是undefined,我们给它写一个set方法,不就可以了吗?
var descriptor = Object.getOwnPropertyDescriptor(DOMTokenList.prototype,"length");descriptor.set = function(value){this.length = value;}Object.defineProperty(DOMTokenList.prototype,"length",descriptor); 然后运行,var descriptor = Object.getOwnPropertyDescriptor(DOMTokenList.prototype,"length");descriptor.set = function(value){delete DOMTokenList.prototype.length;this.length = value;}Object.defineProperty(DOMTokenList.prototype,"length",descriptor); 这样,DOMTokenList也就支持了push,pop等等操作了。Array.prototype.push.call(document.body.classList,"abc")然后再行封装
DOMTokenList.prototype.push = function(){Array.prototype.push.call(document.body.classList,Array.prototype.slice.call(arguments));}Array.prototype.slice.call(arguments)方法用于把arguments对象转换为数组。