Вопрос

А new Ключевое слово в JavaScript может сбить с толку, когда оно впервые встречается, поскольку люди склонны думать, что JavaScript не является объектно-ориентированным языком программирования.

  • Что это такое?
  • Какие проблемы он решает?
  • Когда это уместно, а когда нет?
Это было полезно?

Решение

Он делает 5 вещей:

  1. Он создает новый объект.Тип этого объекта просто объект.
  2. Он устанавливает внутреннюю, недоступную, [[опытный образец]] (т.е. __прото__) свойство быть внешним, доступным, опытный образец объект (каждый функциональный объект автоматически имеет опытный образец свойство).
  3. Это делает this переменная указывает на вновь созданный объект.
  4. Он выполняет функцию конструктора, используя вновь созданный объект всякий раз, когда this упомянуто.
  5. Она возвращает вновь созданный объект, если только функция-конструктор не возвращает не-null ссылка на объект.В этом случае вместо этого возвращается ссылка на этот объект.

Примечание: функция-конструктор относится к функции после new ключевое слово, как в

new ConstructorFunction(arg1, arg2)

Как только это будет сделано, если будет запрошено неопределенное свойство нового объекта, скрипт проверит свойство объекта. [[опытный образец]] вместо этого объект для собственности.Вот как вы можете получить что-то похожее на традиционное наследование классов в JavaScript.

Самое сложное в этом — пункт номер 2.Каждый объект (включая функции) имеет внутреннее свойство, называемое [[опытный образец]].Он может только быть установлен во время создания объекта, либо с помощью новый, с Object.create, или на основе литерала (функции по умолчанию — Function.prototype, числа — Number.prototype и т. д.).Его можно прочитать только с помощью Object.getPrototypeOf(someObject).Есть нет другой способ установить или прочитать это значение.

Функции, помимо скрытых [[опытный образец]] собственность, также есть свойство под названием опытный образец, и именно к нему вы можете получить доступ и изменить его, чтобы предоставить унаследованные свойства и методы для создаваемых вами объектов.


Вот пример:

ObjMaker = function() {this.a = 'first';};
// ObjMaker is just a function, there's nothing special about it that makes 
// it a constructor.

ObjMaker.prototype.b = 'second';
// like all functions, ObjMaker has an accessible prototype property that 
// we can alter. I just added a property called 'b' to it. Like 
// all objects, ObjMaker also has an inaccessible [[prototype]] property
// that we can't do anything with

obj1 = new ObjMaker();
// 3 things just happened.
// A new, empty object was created called obj1.  At first obj1 was the same
// as {}. The [[prototype]] property of obj1 was then set to the current
// object value of the ObjMaker.prototype (if ObjMaker.prototype is later
// assigned a new object value, obj1's [[prototype]] will not change, but you
// can alter the properties of ObjMaker.prototype to add to both the
// prototype and [[prototype]]). The ObjMaker function was executed, with
// obj1 in place of this... so obj1.a was set to 'first'.

obj1.a;
// returns 'first'
obj1.b;
// obj1 doesn't have a property called 'b', so JavaScript checks 
// its [[prototype]]. Its [[prototype]] is the same as ObjMaker.prototype
// ObjMaker.prototype has a property called 'b' with value 'second'
// returns 'second'

Это похоже на наследование классов, потому что теперь любые объекты, которые вы создаете с помощью new ObjMaker() также окажется, что он унаследовал свойство «b».

Если вам нужно что-то вроде подкласса, сделайте следующее:

SubObjMaker = function () {};
SubObjMaker.prototype = new ObjMaker(); // note: this pattern is deprecated!
// Because we used 'new', the [[prototype]] property of SubObjMaker.prototype
// is now set to the object value of ObjMaker.prototype.
// The modern way to do this is with Object.create(), which was added in ECMAScript 5:
// SubObjMaker.prototype = Object.create(ObjMaker.prototype);

SubObjMaker.prototype.c = 'third';  
obj2 = new SubObjMaker();
// [[prototype]] property of obj2 is now set to SubObjMaker.prototype
// Remember that the [[prototype]] property of SubObjMaker.prototype
// is ObjMaker.prototype. So now obj2 has a prototype chain!
// obj2 ---> SubObjMaker.prototype ---> ObjMaker.prototype

obj2.c;
// returns 'third', from SubObjMaker.prototype

obj2.b;
// returns 'second', from ObjMaker.prototype

obj2.a;
// returns 'first', from SubObjMaker.prototype, because SubObjMaker.prototype 
// was created with the ObjMaker function, which assigned a for us

Я прочитал кучу всякой ерунды на эту тему, прежде чем наконец нашел эта страница, где это очень хорошо объяснено с красивыми диаграммами.

Другие советы

Предположим, у вас есть эта функция:

var Foo = function(){
  this.A = 1;
  this.B = 2;
};

Если вы вызовете это как отдельную функцию, например:

Foo();

Выполнение этой функции добавит два свойства в window объект (A и B).Он добавляет его в window потому что window это объект, который вызвал функцию, когда вы выполняете ее таким образом, и this в функции — это объект, вызвавший функцию.По крайней мере, в Javascript.

Теперь назовите это так с помощью new:

var bar = new Foo();

Что произойдет, если вы добавите new вызову функции заключается в том, что создается новый объект (просто var bar = new Object()) и что this внутри функции указывает на новый Object вы только что создали, а не к объекту, вызвавшему функцию.Так bar теперь является объектом со свойствами A и B.Конструктором может быть любая функция, просто это не всегда имеет смысл.

В дополнение к ответу Дэниела Ховарда, вот что new делает (или, по крайней мере, кажется, делает):

function New(func) {
    var res = {};
    if (func.prototype !== null) {
        res.__proto__ = func.prototype;
    }
    var ret = func.apply(res, Array.prototype.slice.call(arguments, 1));
    if ((typeof ret === "object" || typeof ret === "function") && ret !== null) {
        return ret;
    }
    return res;
}

Пока

var obj = New(A, 1, 2);

эквивалентно

var obj = new A(1, 2);

Для новичков, чтобы лучше понять это

попробуйте следующий код в консоли браузера.

function Foo() { 
    return this; 
}

var a = Foo();       //returns window object
var b = new Foo();   //returns empty object of foo

a instanceof Window;  // true
a instanceof Foo;     // false

b instanceof Window;  // false
b instanceof Foo;     // true

Теперь вы можете прочитать ответ вики-сообщества :)

Так что, вероятно, не для создания экземпляров объекта

Он используется именно для этого.Вы определяете конструктор функции следующим образом:

function Person(name) {
    this.name = name;
}

var john = new Person('John');

Однако дополнительное преимущество ECMAScript заключается в том, что вы можете расширить его с помощью .prototype собственность, поэтому мы можем сделать что-то вроде...

Person.prototype.getName = function() { return this.name; }

Все объекты, созданные с помощью этого конструктора, теперь будут иметь getName из-за цепочки прототипов, к которой у них есть доступ.

JavaScript является объектно-ориентированный язык программирования, используемый именно для создания экземпляров.Он основан на прототипах, а не на классах, но это не означает, что он не объектно-ориентирован.

Javascript — это динамический язык программирования, который поддерживает парадигму объектно-ориентированного программирования и используется для создания новых экземпляров объекта.

Классы не обязательны для объектов — Javascript — это на основе прототипа язык.

Уже есть несколько отличных ответов, но я публикую новый, чтобы подчеркнуть свое наблюдение по делу. III ниже о том, что происходит, когда у вас есть явный оператор возврата в функции, которую вы выполняете. newподнимаюсь.Посмотрите на следующие случаи:

Случай I:

var Foo = function(){
  this.A = 1; 
  this.B = 2;
};
console.log(Foo()); //prints undefined
console.log(window.A); //prints 1

Выше приведен простой случай вызова анонимной функции, на которую указывает Foo.Когда вы вызываете эту функцию, она возвращает undefined.Поскольку явного оператора возврата нет, интерпретатор JavaScript принудительно вставляет return undefined; оператор в конце функции.Здесь окно — это объект вызова (контекстный this), который становится новым A и B характеристики.

Случай II:

var Foo = function(){
  this.A = 1;
  this.B = 2;
};
var bar = new Foo();
console.log(bar()); //illegal isn't pointing to a function but an object
console.log(bar.A); //prints 1

Здесь интерпретатор JavaScript видит new Ключевое слово создает новый объект, который действует как объект вызова (контекстный this) анонимной функции, на которую указывает Foo.В этом случае A и B станут свойствами вновь созданного объекта (вместо объекта окна).Поскольку у вас нет явного оператора возврата, интерпретатор JavaScript принудительно вставляет оператор возврата, чтобы вернуть новый объект, созданный в результате использования new ключевое слово.

Случай III:

var Foo = function(){
  this.A = 1;
  this.B = 2;
  return {C:20,D:30}; 
};
var bar = new Foo();
console.log(bar.C);//prints 20
console.log(bar.A); //prints undefined. bar is not pointing to the object which got created due to new keyword.

Здесь интерпретатор JavaScript снова видит new Ключевое слово создает новый объект, который действует как объект вызова (контекстный this) анонимной функции, на которую указывает Foo.Снова, A и B станут свойствами вновь созданного объекта.Но на этот раз у вас есть явный оператор возврата, поэтому интерпретатор JavaScript нет сделать что-нибудь свое.

На что обратить внимание на всякий случай III заключается в том, что объект, создаваемый благодаря new Ключевое слово потерялось с вашего радара. bar на самом деле указывает на совершенно другой объект, который не является тем, который интерпретатор JavaScript создал из-за new ключевое слово.

Цитирую Дэвида Фланагана из JavaScripit:Полное руководство (6-е издание), гл.4, страница № 62:

Когда оценивается выражение создания объекта, JavaScript сначала создает новый пустой объект, точно так же, как тот, который создан инициализатором объекта {}.Затем он вызывает указанную функцию с указанными аргументами, передавая новый объект как значение этого ключевого слова.Затем функция может использовать это для инициализации свойств недавно созданного объекта.Функции, написанные для использования в качестве конструкторов, не возвращают значение, а значение выражения создания объекта - это недавно созданный и инициализированный объект.Если конструктор действительно возвращает значение объекта, это значение становится значением выражения создания объекта, а недавно созданный объект отбрасывается.

---Дополнительная информация---

Функции, используемые в приведенном выше фрагменте кода, имеют специальные имена в мире JS, как показано ниже:

Случай I и II - Функция конструктора

Случай III - Заводская функция.Заводские функции не должен использоваться с new ключевое слово, которое я сделал, чтобы объяснить концепцию в текущей теме.

О разнице между ними вы можете прочитать в этот нить.

иногда код проще слов:

var func1 = function (x) { this.x = x; }                    // used with 'new' only
var func2 = function (x) { var z={}; z.x = x; return z; }   // used both ways
func1.prototype.y = 11;
func2.prototype.y = 12;

A1 = new func1(1);      // has A1.x  AND  A1.y
A2 =     func1(1);      // undefined ('this' refers to 'window')
B1 = new func2(2);      // has B1.x  ONLY
B2 =     func2(2);      // has B2.x  ONLY

Что касается меня, пока я не создаю прототип, я использую стиль func2, поскольку он дает мне немного больше гибкости внутри и снаружи функции.

А new Ключевое слово изменяет контекст, в котором запускается функция, и возвращает указатель на этот контекст.

Когда вы не используете new ключевое слово, контекст, в котором функция Vehicle() работает тот же контекст, из которого вы вызываете Vehicle функция.А this Ключевое слово будет относиться к тому же контексту.Когда вы используете new Vehicle(), создается новый контекст, поэтому ключевое слово this внутри функции относится к новому контексту.Взамен вы получаете вновь созданный контекст.

А new Ключевое слово предназначено для создания новых экземпляров объектов.И да, javascript — это динамический язык программирования, поддерживающий парадигму объектно-ориентированного программирования.Соглашение об именовании объектов таково: всегда используйте заглавную букву для объектов, экземпляры которых должны быть созданы с помощью ключевого слова new.

obj = new Element();

А new Ключевое слово создает экземпляры объектов, используя функции в качестве конструктора.Например:

var Foo = function() {};
Foo.prototype.bar = 'bar';

var foo = new Foo();
foo instanceof Foo; // true

Экземпляры наследуются от prototype функции-конструктора.Итак, учитывая пример выше...

foo.bar; // 'bar'

Что ж, JavaScript сам по себе может сильно отличаться от платформы к платформе, поскольку он всегда является реализацией исходной спецификации EcmaScript.

В любом случае, независимо от реализации, все реализации JavaScript, соответствующие спецификации EcmaScript, дадут вам объектно-ориентированный язык.По стандарту ES:

Ecmascript-это объектно-ориентированный язык программирования для выполнения вычислений и манипулирования вычислительными объектами в среде хоста.

Итак, теперь мы пришли к соглашению, что JavaScript является реализацией EcmaScript и, следовательно, является объектно-ориентированным языком.Определение new операция на любом объектно-ориентированном языке говорит, что такое ключевое слово используется для создания экземпляра объекта из класса определенного типа (включая анонимные типы, в таких случаях, как C#).

В EcmaScript мы не используем классы, как вы можете прочитать из спецификации:

ECMAScript не использует классы, подобные тем, которые есть в C++, Smalltalk или Java.Вместо этого объекты могут создаваться различными способами, включая буквальную нотацию или через конструкторы, которые создают объекты, а затем выполняют код, который инициализирует все или часть из них путем назначения начальных значений их свойствам.Каждый конструктор - это функция, которая имеет свойство, названное «прототип», которое используется для реализации прототипа - основанного на наследии и общих свойствах.Объекты создаются
использование конструкторов в новых выражениях;Например, новая дата (2009,11) создает новый объект даты.Вызов конструктора без использования нового имеет последствия, которые зависят от конструктора.Например, Date () создает строковое представление текущей даты и времени, а не объекта.

Краткое содержание:

А new Ключевое слово используется в JavaScript для создания объекта из функции-конструктора.А new Ключевое слово должно быть помещено перед вызовом функции конструктора и будет выполнять следующие действия:

  1. Создает новый объект
  2. Устанавливает прототип этого объекта в свойство прототипа функции-конструктора.
  3. Связывает this ключевое слово для вновь созданного объекта и выполняет функцию конструктора
  4. Возвращает вновь созданный объект

Пример:

function Dog (age) {
  this.age = age;
}

const doggie = new Dog(12);

console.log(doggie);
console.log(doggie.__proto__ === Dog.prototype) // true

Что именно происходит:

  1. const doggie говорит:Нам нужна память для объявления переменной.
  2. Оператор присваивания = говорит:Мы собираемся инициализировать эту переменную выражением после =
  3. Выражение new Dog(12).Движок JS видит новое ключевое слово, создает новый объект и устанавливает прототип Dog.prototype.
  4. Функция конструктора выполняется с помощью this значение, установленное для нового объекта.На этом этапе новому созданному объекту собачки присваивается возраст.
  5. Вновь созданный объект возвращается и присваивается переменной Doggie.
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top