标签:
Javascript中实现不加new关键字的构造函数
一般而言,在Javascript中创建对象时需要使用关键字new,但是某些时候,开发者希望无论new关键字有没有被显式使用,构造函数都可以被正常调用,即构造函数同时还具备简单工厂的职能。Javascript的一个特性使得这样的实现变得可行:如果构造函数中返回了对象,无论有没有使用new关键字,最终返回的值都是函数return的值。
基于这点特性,本文介绍了四种实现方式,抛砖引玉,欢迎拍砖~
1. 在构造函数中返回对象字面量
1 function Person(name) { 2 return { 3 name: name, 4 getName: function () { 5 return this.name; 6 } 7 }; 8 } 9 console.log(new Person(‘Ralph‘).getName()); //Ralph 10 console.log(Person(‘Ralph‘).getName()); //Ralph
缺点:
不方便控制prototype属性,不利于高效扩展对象方法,instanceof操作符失效且constructor属性丢失
2. 在构造函数中使用内部函数构造对象
1 function Person(name) { 2 // lazy loading,在Person函数第一次被调用时初始化内部函数_Person 3 if (!Person.inited) { 4 Person._Person = function (name) { 5 this.name = name; 6 }; 7 // 可以利用prototype进行方法扩展 8 Person._Person.prototype = { 9 // 正常使用constructor属性 10 constructor: Person, 11 getName: function () { 12 return this.name; 13 } 14 }; 15 // 可以正常使用instanceof操作符 16 Person.prototype = Person._Person.prototype; 17 // 标记为已初始化 18 Person.inited = true; 19 } 20 return new Person._Person(name); 21 } 22 console.log(new Person(‘Ralph‘).getName()); //Ralph 23 console.log(Person(‘Ralph‘).getName()); //Ralph
缺点:
编码较为复杂,需要_Person作为辅助的内部构造函数,且需要手动修改prototype和constructor等属性
3. 利用instanceof操作符
1 function Person(name) { 2 // 如果使用了new,this指向新生成的Person实例 3 // 如果直接调用Person没有使用new,这里的this指向window对象 4 if (!(this instanceof Person)) { 5 return new Person(name); 6 } 7 this.name = name; 8 } 9 Person.prototype.getName = function () { 10 return this.name; 11 }; 12 console.log(new Person(‘Ralph‘).getName()); //Ralph 13 console.log(Person(‘Ralph‘).getName()); //Ralph
缺点:
在判断this instanceof Person时需要指明构造函数名称Person,不够抽象,修改构造函数名称时需要手动修改该语句
4. 利用callee属性和constructor属性
1 function Person(name) { 2 // arguments.callee指向Person函数 3 // this.constructor仅在使用了new的情形下指向Person函数 4 if (arguments.callee !== this.constructor) { 5 return new Person(name); 6 } 7 this.name = name; 8 } 9 Person.prototype.getName = function () { 10 return this.name; 11 }; 12 console.log(new Person(‘Ralph‘).getName()); //Ralph 13 console.log(Person(‘Ralph‘).getName()); //Ralph
缺点:
strict模式下无法使用callee属性
(全文完)
标签:
原文地址:http://www.cnblogs.com/front-end-ralph/p/4868107.html