Подтвердить что ты не робот

Можно ли создать объект JavaScript без использования нового ключевого слова?

Вот что я хотел бы сделать:

function a() {
  // ...
}
function b() {
  //  Some magic, return a new object.
}
var c = b();

c instanceof b // -> true
c instanceof a // -> true
b instanceof a // -> true

Возможно ли это? Я могу сделать b легко экземпляром a, подключив a к своей цепочке прототипов, но тогда мне нужно сделать new b(), чего я пытаюсь избежать. Я хочу, чтобы это было возможно?

Обновление: Я чувствую, что это возможно при разумном использовании b.__proto__ = a.prototype. Я буду экспериментировать больше после работы.

Обновление 2: Ниже приводится то, что кажется самым близким, которое вы можете получить, что достаточно для меня. Спасибо всем за интересные ответы.

function a() {
  // ...
}
function b() {
  if (!(this instanceof arguments.callee)) {
    return new arguments.callee();
  }
}
b.__proto__ = a.prototype

var c = b();
c instanceof b // -> true
c instanceof a // -> false
b instanceof a // -> true

Обновление 3: Я нашел именно то, что я хотел в блоге в блоге "конструкторы мощности" , как только я добавлена ​​существенная строка b.__proto__ = a.prototype:

var object = (function() {
     function F() {}
     return function(o) {
         F.prototype = o;
         return new F();
     };
})();

function a(proto) {
  var p = object(proto || a.prototype);
  return p;
}

function b(proto) {
  var g = object(a(proto || b.prototype));
  return g;
}
b.prototype = object(a.prototype);
b.__proto__ = a.prototype;

var c = b();
c instanceof b // -> true
c instanceof a // -> true
b instanceof a // -> true
a() instanceof a // -> true
4b9b3361

Ответ 1

Вы можете использовать этот шаблон:

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, которую я создал с использованием этого шаблона.

Ответ 2

Что не так с использованием ключевого слова new?

Во всяком случае, кажется, что лучше всего читать на Javascript-наследовании: http://javascript.crockford.com/inheritance.html

Ответ 4

Вы не можете избежать new в общем случае (не доходя до крайностей, в соответствии с статьей Crockford Zoidberg, косвенно связанной с), если вы хотите, чтобы наследование и instanceof работали, но затем (снова), почему вам нужно или нужно?

Единственная причина, по которой я могу думать о том, где вы хотите этого избежать, - это попытаться передать функцию-конструктор другому фрагменту кода, который не знает его как конструктор. В этом случае просто заверните его в функцию factory:

function b() {
    // ...
}
function makeB() {
    return new b();
}
var c = makeB();

Ответ 5

Простой ответ на ваш конкретный вопрос: no.

Это поможет вам определить, почему вы хотите избежать new. Возможно, шаблоны, на которые ссылается один из других ответов, помогут. Однако ни один из них не приводит к тому, что instanceof возвращает true в ваших тестах.

Новая операция по существу: -

var x = (function(fn) { var r = {}; fn.call(r); return r;}(b);

Однако существует разница в том, что конструкция fn привязана к объекту с использованием некоторого внутреннего свойства (да, вы можете получить его с помощью constructor, но установка его не имеет такого же эффекта). Единственный способ получить instanceof для работы по назначению - использовать ключевое слово new.

Ответ 6

Вы можете создавать экземпляры без нового оператора (вот большая статья, написанная об этом Дугласом Крокфордом http://yuiblog.com/blog/2006/11/13/javascript-we-hardly-new-ya/). Но это не поможет вам с историей "instanceof".

Ответ 7

Да, вы можете это сделать.

var User = function() {
  var privateMethod = function() {
    alert('hello');
  }

  return {
    sayHello : function() {
      privateMethod();
      this.done = true;
    }
  }
}

var user1 = User();

Что-то не так с этим методом?

Ответ 8

Единственный способ заставить instanceof работать - использовать новое ключевое слово. instanceof exploits ____proto____, который устанавливается новым.

Ответ 9

Объекты JavaScript могут быть созданы без использования нового ключевого слова.

Например, следующая функция возвращает объект без использования нового ключевого слова

function a(){
    var obj ={};
    obj.name = "hello";
    obj.age = 12;

    return obj;

}

Ответ 10

В ярлыке javascript вы можете использовать eval (unescape ( "..." )) для создания объекта без "нового" оператора:

javascript:xhr=eval(unescape('new\x20XMLHttpRequest();'));alert(xhr);

Ответ 11

Для тех, кто может найти это через Google (например, я...), я разработал оригинальное решение для более широкого использования:

var myObject = function() {}; // hint: Chrome debugger will name the created items 'myObject'

var object = (function(myself, parent) {  
     return function(myself, parent) {
         if(parent){
             myself.prototype = parent;
         }
         myObject.prototype = myself.prototype;
         return new myObject();
     };
})(); 

a = function(arg) {
     var me = object(a);
     me.param = arg;
     return me;
};

b = function(arg) {
    var parent = a(arg),
        me = object(b, parent)
    ;
    return me;
};

var instance1 = a();
var instance2 = b("hi there");

console.log("---------------------------")
console.log('instance1 instance of a: ' +  (instance1 instanceof a))
console.log('instance2 instance of b: ' +  (instance2 instanceof b))
console.log('instance2 instance of a: ' +  (instance2 instanceof a))
console.log('a() instance of a: ' +  (a() instanceof a))
console.log(instance1.param)
console.log(instance2.param)

Ответ 12

Используя Object.create и классический Function.prototype. Правильно создавая цепочку прототипов, вы сохраняете правильное функционирование ключевого слова instanceof без использования ключевого слова new.

function A() {
    return Object.create(A.prototype);
}

function B() {
    return Object.create(B.prototype);
}

B.prototype = Object.create(A.prototype);

var c = B();

assert(c instanceof A);
assert(c instanceof B);

Ответ 13

Да.

function _new(classConstructor, ...args) {
  var obj = Object.create(classConstructor.prototype);
  classConstructor.call(obj, ...args);
  return obj;
}

function test_new() {
  function TestClass(name, location) {
    this._name = name;
    this._location = location;
    this.getName = function() {
      return this._name;
    }
  }

  TestClass.prototype.getLocation = function() {
    return this._location;
  }
  TestClass.prototype.setName = function(newName) {
    this._name = newName;
  }

  const a = new TestClass('anil', 'hyderabad');
  const b = _new(TestClass, 'anil', 'hyderabad');

  const assert = console.assert
  assert(a instanceof TestClass)
  assert(b instanceof TestClass)
  assert(a.constructor.name === 'TestClass');
  assert(b.constructor.name === 'TestClass');
  assert(a.getName() === b.getName());
  assert(a.getLocation() === b.getLocation());
  a.setName('kumar');
  b.setName('kumar');
  assert(a.getName() === b.getName());
  console.log('All is well')
}
test_new()