设为首页 加入收藏

TOP

JavaScript中实现不加new关键字的构造函数
2015-11-10 13:45:27 来源: 作者: 【 】 浏览:2
Tags:JavaScript 实现 new 关键字 构造 函数

一般而言,在java script中创建对象时需要使用关键字new,但是某些时候,开发者希望无论new关键字有没有被显式使用,构造函数都可以被正常调用,即构造函数同时还具备简单工厂的职能。java script的一个特性使得这样的实现变得可行:如果构造函数中返回了对象,无论有没有使用new关键字,最终返回的值都是函数return的值。


基于这点特性,本文介绍了四种实现方式,抛砖引玉,欢迎拍砖~


1. 在构造函数中返回对象字面量


function Person(name) {
? ? return {
? ? ? ? name: name,
? ? ? ? getName: function () {
? ? ? ? ? ? return this.name;
? ? ? ? }
? ? };
}
console.log(new Person('Ralph').getName()); //Ralph
console.log(Person('Ralph').getName()); //Ralph


缺点:


不方便控制prototype属性,不利于高效扩展对象方法,instanceof操作符失效且constructor属性丢失


2. 在构造函数中使用内部函数构造对象


function Person(name) {
? ? // lazy loading,在Person函数第一次被调用时初始化内部函数_Person
? ? if (!Person.inited) {
? ? ? ? Person._Person = function (name) {
? ? ? ? ? ? this.name = name;
? ? ? ? };
? ? ? ? // 可以利用prototype进行方法扩展
? ? ? ? Person._Person.prototype = {
? ? ? ? ? ? // 正常使用constructor属性
? ? ? ? ? ? constructor: Person,
? ? ? ? ? ? getName: function () {
? ? ? ? ? ? ? ? return this.name;
? ? ? ? ? ? }
? ? ? ? };
? ? ? ? // 可以正常使用instanceof操作符
? ? ? ? Person.prototype = Person._Person.prototype;
? ? ? ? // 标记为已初始化
? ? ? ? Person.inited = true;
? ? }
? ? return new Person._Person(name);
}
console.log(new Person('Ralph').getName()); //Ralph
console.log(Person('Ralph').getName()); //Ralph


缺点:


编码相对较为复杂,需要_Person作为辅助的内部构造函数,且需要手动修改prototype和constructor等属性


3. 利用instanceof操作符


function Person(name) {
? ? // 如果使用了new,this指向新生成的Person实例
? ? // 如果直接调用Person没有使用new,这里的this指向window对象
? ? if (!(this instanceof Person)) {
? ? ? ? return new Person(name);
? ? }
? ? this.name = name;
}
Person.prototype.getName = function () {
? ? return this.name;
};
console.log(new Person('Ralph').getName()); //Ralph
console.log(Person('Ralph').getName()); //Ralph


缺点:


在判断this instanceof Person时需要指明构造函数名称Person,抽象程度不够高,修改构造函数名称时需要手动修改该语句


4. 利用callee属性和constructor属性


function Person(name) {
? ? // arguments.callee指向Person函数
? ? // this.constructor仅在使用了new的情形下指向Person函数
? ? if (arguments.callee !== this.constructor) {
? ? ? ? return new arguments.callee(name);
? ? }
? ? this.name = name;
}
Person.prototype.getName = function () {
? ? return this.name;
};
console.log(new Person('Ralph').getName()); //Ralph
console.log(Person('Ralph').getName()); //Ralph


缺点:
strict模式下无法使用callee属性


(全文完)


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Android 使用shape制作drawable素.. 下一篇Python 实现重启路由器

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: