Вы можете использовать этот шаблон:
function SomeConstructor(){
if (!(this instanceof SomeConstructor)){
return new SomeConstructor();
}
//the constructor properties and methods here
}
, после чего вы можете сделать:
var myObj = SomeConstructor();
В дополнение к этому (довольно старому) ответу: вы можете использовать шаблон модуля для создания объекта:
function Person(name, age, male) {
name = name || 'unknown';
age = age || 0;
function get() {
return ['This person is called ', name,
(!male ? ', her' : ', his'),' age is ',
age].join('');
}
function setAge(nwage) {
age = nwage;
}
return Object.freeze({get: get, setAge: setAge});
}
// usage
var jane = Person('Jane', 23)
,charles = Person('Charles', 32, 1)
,mary = Person('Mary', 16);
console.log(jane.get()); //=> This person is called Jane, her age is 23
mary.setAge(17);
console.log(mary.get()); //=> This person is called Mary, her age is 17
Вот jsFiddle для некоторой функциональности Date
, которую я создал с использованием этого шаблона.
Полизаливка для нового оператора:
function sampleClass() {
this.cname = "sample";
}
sampleClass.prototype.getCname = function() {
return this.cname;
}
const newPolyfill = function(fname) {
if (typeof fname !== "function")
throw Error("can't call new on non-functional input");
let newFun = {};
newFun.__proto__ = Object.assign(fname.prototype);
fname.prototype.constructor();
for (let key in fname.prototype) {
if (typeof fname.prototype[key] !== "function") {
newFun[key] = fname.prototype[key];
delete newFun.__proto__[key];
delete fname.__proto__[key];
}
}
return newFun;
}
let newObj = new sampleClass();
console.log("new obj", newObj);
console.log("new cname", newObj.getCname());//sample
let newPolyObj = newPolyfill(sampleClass);
console.log("new poly obj", newPolyObj);
console.log("newPly cname", newPolyObj.getCname());//sample
console.log(newPolyObj instanceof(sampleClass)) // true
Вы можете создавать экземпляры без оператора new (вот отличная статья, написанная об этом Дугласом Крокфордом http://yuiblog.com/blog/2006/11/13/javascript -мы-вряд-нов-я / ). Но это не поможет вам с историей "instanceof".
Вы не можете избежать new
в общем случае (не впадая в крайности, согласно статье Крокфорда, с которой Зойдберг косвенно связана), если вы хотите наследования и instanceof
, но тогда (опять же), зачем вам это нужно или нужно?
Единственная причина, по которой я могу придумать, где вы бы хотели этого избежать, - это если вы пытаетесь передать функцию конструктора к другому фрагменту кода, который не знает, что это конструктор. В этом случае просто заключите его в фабричную функцию:
function b() {
// ...
}
function makeB() {
return new b();
}
var c = makeB();
Простой ответ на ваш конкретный вопрос: нет
Это поможет вам определить, почему вы хотите избегать нового
. Возможно, вам помогут шаблоны, на которые ссылается один из других ответов. Однако ни один из них не приводит к тому, что instanceof
возвращает true в ваших тестах.
Новая операция по существу: -
var x = (function(fn) { var r = {}; fn.call(r); return r;}(b);
Однако есть разница в том, что построение fn
прикреплено к объекту, используя какое-то внутреннее свойство (да, вы можете получить его с помощью конструктора
, но его установка не имеет такого же эффекта). Единственный способ заставить instanceof
работать должным образом - это использовать ключевое слово new
.
Кто-то опубликовал статью Дугласа Крокфорда в этом вопросе, и она объясняет, о чем вы спрашиваете.
OO Шаблон конструктора Javascript: неоклассический против прототипа
Что не так с использованием ключевого слова new
?
В любом случае, похоже, что лучше всего прочитать о наследовании Javascript: http://javascript.crockford.com/inheritance.html
The only way to get instanceof to work is to use the new keyword. instanceof exploits ____proto____ which is established by new.
JavaScript objects can be created without using the new keyword.
For example the following function returns an object without using new keyword
function a(){ var obj ={}; obj.name = "hello"; obj.age = 12; return obj; }