恶趣味构造函数
October 29, 2018
引子
理论上说,只要对函数使用new
语法,任何function
都可以作为constructor
创建新实例,但是如果function
不按常理出牌呢?还可以实现创建新实例的目标吗?
注:本文内容为
JavaScript Ninja
的读书笔记。
带返回值的构造函数
- 返回值为基本类型
function retPrimType() {
this.value = 'I am a function returning a primitive type';
this.getMyThis = function() {
return this;
};
return 'I return a new Object as this';
}
const a = new retPrimType();
console.log(retPrimType()); //'I return a new Object as this'
console.log(a.getMyThis() === a); //true
- 返回值为对象
const ref = { key: 'object' };
function retObjectType() {
this.value = 'I am a funtion returning an Object';
this.getMyThis = function() {
return this;
};
return ref;
}
const b = new retObjectType();
console.log(retObjectType()); //{key:'object'}
console.log(b.getMyThis === b); // error: b.getMyThis is not a function
console.log(b === ref); //true
const c = new retObjectType();
console.log(b === c); //true
-
小结
function
返回基本类型,new
之后其返回值被忽略,依然能够创建新实例,并且this
的指向正确function
返回对象,new 之后该对象将被返回,无法创建新实例
一点引申: 单例模式
开一点脑洞,如果要求某个对象使用new
后只能返回同一个实例,即实现单例模式,如何利用上面的结论来实现?
const singleton = (function() {
const retObj = { key: 'I am singleton!' };
return function() {
return retObj;
};
})();
const a = new singleton();
const b = new singleton();
console.log(a === b); //true
a.key = 'everyone changes with me';
console.log(a); //{key: 'everyone changes with me'}
console.log(b); //{key: 'everyone changes with me'}
用 IIFE+闭包构造一个singleton
对象,它的值就是内层匿名函数,可以访问其外层自由变量retObj
。按照上面总结的规则,每当对singleton
执行new
操作时,它总是会返回对象retObj
,这样就实现了恶趣味单例模式。