注意:JavaScript中没有类的概念,这里只是便于称呼。
我们知道,对象属性可以在创建对象之后动态定义,例如:通过new关键字创建一个类对象,然后新增属性和方法。 var obj1 = new Object; obj1.color="red"; obj1.doors=4; obj1.mpg=23; obj1.showColor = function() {// 该属性实际指向函数的指针, 意味着该属性是个方法. alert(this.color); } //调用showColor方法 obj1.showColor(); */ /*
// 可将方法变量showColor指向外部的具名函数,则在类内部只需定义一个变量showColor存储具名函数的指针(指针指向了showColor在heap中的位置。) function showColor(){ alert(this.color); }
obj1.showColor = showColor;// 显然,若没有看到定义的外部函数showColor(),一般人是无法察觉这是obj1对象的一个方法 // 上述创建方式仅仅是创建了一个实例,要创建多个实例,可通过工厂函数进行。 function createCar(color, doors, mpg) { var tmpCar = new Object(); tmpCar.color=color; tmpCar.doors=doors; tmpCar.mpg=mpg; tmpCar.showColor = showColor; return tmpCar; } */ /* // 由于通过工厂函数方式创建对象导致诸多问题,进而产生了构造函数的概念 function Car(color, doors, mpg){//函数名第一个字母要大写 this.color=color; this.doors=doors; this.mpg=mpg; this.showColor = function(){ alert(this.color); } } * */ //通过构造函数的方式创建类,默认情况下无返回值,使用this关键字访问新创建的对象. /** * 通过构造函数定义类和通过工厂函数方式定义类具有同样的问题: * 1. 每次创建一个实例时,都会重复生成函数;(可以优化为只生成一次函数,那么如何优化呢?) * 2. 若在构造函数外部构造函数,则会使得showColor不像一个方法: * function showColor(){ alert(this.color); } function Car(color, doors, mpg){//函数名第一个字母要大写 this.color=color; this.doors=doors; this.mpg=mpg; this.showColor = showColor;//语义歧义 } * 由此产生了原型方式 */ /* function Car(){ } // 这里通过给Car的prototype属性添加属性去定义Car对象的属性. Car.prototype.color="red"; Car.prototype.doors=4; Car.prototype.mpg=23; Car.prototype.showColor = function(){ alert(this.color); } */ // 通过上述定义类的方式使得所有类实例都操作了同一个东西. // 由此产生:构造函数/原型方式相互结合定义类 function Car(color, doors, mpg){ this.color = color; this.doors=doors; this.mpg=mpg; } Car.prototype.showColor = function() { alert(this.color); } //通过fireBugs调试可以看出, 创建一个实例时,构造函数执行一次 //var car1 = new Car("red", 4, 35); //var car2 = new Car("blue", 5, 24); //当属性函数(方法)被该实例调用时,才去执行该方法.(创建实例时未被属性函数未被生成) //car1.showColor(); //car2.showColor(); //这里仅仅创建了showColor()函数的一个实例,所以没有内存浪费. /* // 动态原型方法 function Car2(color, doors, mpg){ this.color = color; this.doors = doors; this.mpg = mpg; //alert(typeof Car.initialized == 'undefined'); if (typeof Car._initialized == 'undefined'){ Car.prototype.showColor = function() { alert(this.color); }; Car._initialized = true; } } var car1 = new Car2("red", 4, 35); var car2 = new Car2("blue", 5, 24); car2.showColor(); //当属性函数(方法)被该实例调用时,才去执行该方法.(创建实例时未被属性函数未被生成) car1.showColor(); * */
// 注意这里的this._strings_,strings前后加_(有些开发者喜欢使用this._strings),用来说明strings属性是私有的. /** * 注意:1、ECMAScript中的所有对象的所有属性和方法都是公用的; * 2、在属性名前后(或前)加_仅仅是开发者们的一种规约,用于说明哪些属性和方法应该被看作私有的; * 3、记住:这些下划线并不改变这些属性是公用属性的事实. */ function StringBuffer(){ this._strings_ = new Array; } StringBuffer.prototype.append = function(str){ this._strings_.push(str); } StringBuffer.prototype.toString = function(){ return this._strings_.join(""); }
// 测试性能 var d1 = new Date(); var str = ""; for(var i = 0 ; i < 10000 ; i++){ str += "text"; } var d2 = new Date(); document.write("Concatenation with plus: " + (d2.getTime() - d1.getTime()) + " ms");
var d3 = new Date(); var oBuffer = new StringBuffer(); for(var i=0;i<10000;i++){ oBuffer.append("text"); } var sResult = oBuffer.toString(); var d4 = new Date(); document.write("<br />Concatenation with StringBuffer: " + (d4.getTime() - d3.getTime()) + " ms");
转载本文请联系原作者获取授权,同时请注明本文来自程冬科学网博客。 链接地址: https://m.sciencenet.cn/blog-448935-592805.html
上一篇:
浅谈数据库中的事务控制 下一篇:
DOM学习小结(一)