Использование «прототипа» против «этого» в JavaScript?

Вы можете преобразовать массив в список с помощью tolist(), а затем выполнить проверку:

my_list = [[1,1], [2,2]]

print(np.array([1,1]).tolist() in my_list)
print(np.array([1,2]).tolist() in my_list)
758
задан CRABOLO 10 October 2015 в 17:19
поделиться

8 ответов

Я полагаю, что @Matthew Crumley является правильным. Они функционально , если не структурно, эквивалентны. Если Вы используете Firebug для рассмотрения объектов, которые создаются с помощью new, Вы видите, что они - то же. Однако мое предпочтение было бы следующим. Я предполагаю, что просто кажется больше как то, к чему я привык в C#/Java. Таким образом, определите класс, определите поля, конструктора и методы.

var A = function() {};
A.prototype = {
    _instance_var: 0,

    initialize: function(v) { this._instance_var = v; },

    x: function() {  alert(this._instance_var); }
};

РЕДАКТИРОВАНИЕ не означало подразумевать, что объем переменной был частным, я просто пытался проиллюстрировать, как я определяю свои классы в JavaScript. Имя переменной изменилось для отражения этого.

11
ответ дан tvanfosson 10 October 2015 в 17:19
поделиться

Какая разница? => Много.

Я думаю, версия this используется для включения инкапсуляции, то есть сокрытия данных. Это помогает манипулировать закрытыми переменными.

Давайте рассмотрим следующий пример:

var AdultPerson = function() {

  var age;

  this.setAge = function(val) {
    // some housekeeping
    age = val >= 18 && val;
  };

  this.getAge = function() {
    return age;
  };

  this.isValid = function() {
    return !!age;
  };
};

Теперь, структура prototype может применяться следующим образом:

Разные взрослые имеют разный возраст, но все взрослые получить те же права.
Итак, мы добавим его, используя прототип, а не этот.

AdultPerson.prototype.getRights = function() {
  // Should be valid
  return this.isValid() && ['Booze', 'Drive'];
};

Давайте посмотрим на реализацию сейчас.

var p1 = new AdultPerson;
p1.setAge(12); // ( age = false )
console.log(p1.getRights()); // false ( Kid alert! )
p1.setAge(19); // ( age = 19 )
console.log(p1.getRights()); // ['Booze', 'Drive'] ( Welcome AdultPerson )

var p2 = new AdultPerson;
p2.setAge(45);    
console.log(p2.getRights()); // The same getRights() method, *** not a new copy of it ***

Надеюсь, это поможет.

16
ответ дан oozzal 10 October 2015 в 17:19
поделиться

Примеры имеют совсем другие результаты.

Перед рассмотрением различий, следующее должно быть отмечено:

  • конструктор А прототип позволяет совместно использовать методы и значения среди экземпляров через экземпляр, частный [[Prototype]] свойство.
  • функция А это установлено тем, как функция вызвана, или при помощи [1 130] связывают (не обсужденный здесь). Где функция вызвана на объекте (например, myObj.method()) тогда это в рамках метода ссылается на объект. Где это не установлено вызовом, или при помощи [1 133] связывают , он принимает значение по умолчанию к глобальному объекту (окно в браузере) или в строгом режиме, остается неопределенным.
  • JavaScript является объектно-ориентированным языком, т.е. большинство значений является объектами, включая функции. (Строки, числа и булевские переменные не объекты.)

, Таким образом, вот рассматриваемые отрывки:

var A = function () {
    this.x = function () {
        //do something
    };
};

В этом случае, переменной A присваивают значение, которое является ссылкой на функцию. Когда та функция вызвана с помощью [1 110], функция , это не установлено вызовом, таким образом, это принимает значение по умолчанию к глобальному объекту, и выражение this.x эффективно window.x. Результат состоит в том, что ссылка на выражение function на правой стороне присвоена [1 113].

В случае:

var A = function () { };
A.prototype.x = function () {
    //do something
};

что-то совсем другое происходит. В первой строке переменная A присвоена ссылка на функцию. В JavaScript все объекты функций имеют прототип свойство по умолчанию, таким образом, нет никакого отдельного кода для создания объект A.prototype.

Во второй строке, A.prototype.x присвоен ссылка на функцию. Это создаст x свойство, если это не будет существовать или присваивать новое значение, если это делает. Так различие с первым примером, в котором объекте x свойство вовлечено в выражение.

Другой пример ниже. Это подобно первому (и возможно что Вы означали спрашивать о):

var A = new function () {
    this.x = function () {
        //do something
    };
};

В этом примере, new оператор был добавлен перед выражением function так, чтобы функция была вызвана как конструктор. Когда названо с [1 116], функция это установлено сослаться на новый Объект, чей частный [[Prototype]] свойство установлено сослаться на общественность конструктора прототип . Таким образом в операторе присваивания, x свойство будет создано на этом новом объекте. Когда названо как конструктор, функция возвращает этот объект по умолчанию, таким образом, нет никакой потребности в отдельном return this; оператор.

, Чтобы проверить, что А имеет x свойство:

console.log(A.x) // function () {
                 //   //do something
                 // };

Это - редкое использование [1 146] новый , так как единственный способ сослаться на конструктора через [1 147] A.constructor. Было бы намного более распространено сделать:

var A = function () {
    this.x = function () {
        //do something
    };
};
var a = new A();

Другой способ достигнуть подобного результата состоит в том, чтобы использовать сразу вызванное выражение function:

var A = (function () {
    this.x = function () {
        //do something
    };
}());

В этом случае, A присвоил возвращаемое значение вызывания функции на правой стороне. Здесь снова, с тех пор это не установлено в вызове, он сошлется на глобальный объект, и this.x эффективный window.x. Так как функция не возвращается, что-либо, A будет иметь значение [1 124].

Эти различия между двумя подходами также проявляют, если Вы сериализируете и десериализовываете свои объекты JavaScript к/от JSON. Методы, определенные на прототипе объекта, не сериализируются при сериализации объекта который может быть удобным, когда, например, Вы хотите сериализировать просто части данных объекта, но не это - методы:

var A = function () { 
    this.objectsOwnProperties = "are serialized";
};
A.prototype.prototypeProperties = "are NOT serialized";
var instance = new A();
console.log(instance.prototypeProperties); // "are NOT serialized"
console.log(JSON.stringify(instance)); 
// {"objectsOwnProperties":"are serialized"} 

Связанные вопросы :

Заметка на полях: не может быть никаких значительных сбережений памяти между двумя подходами, однако с помощью прототипа для совместного использования методов, и свойства будут, вероятно, использовать меньше памяти, чем каждый экземпляр, имеющий его собственную копию.

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

455
ответ дан 29 revs, 12 users 61% 10 October 2015 в 17:19
поделиться

Прототип является шаблоном класса; который относится ко всем будущим экземплярам его. Принимая во внимание, что это - конкретный экземпляр объекта.

14
ответ дан harropriiz 10 October 2015 в 17:19
поделиться

Первый пример изменяет интерфейс для того объекта только. Второй пример изменяет интерфейс для всего объекта того класса.

27
ответ дан Glenn 10 October 2015 в 17:19
поделиться

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

причина А использовать первую форму состоит в том, чтобы получить доступ к "членам парламента, не занимающим официального поста". Например:

var A = function () {
    var private_var = ...;

    this.x = function () {
        return private_var;
    };

    this.setX = function (new_x) {
        private_var = new_x;
    };
};

из-за правил обзора JavaScript, private_var доступен функции, присвоенной this.x, но не вне объекта.

58
ответ дан Matthew Crumley 10 October 2015 в 17:19
поделиться

Поскольку другие сказали, что первая версия, с помощью "этого" приводит к каждому экземпляру класса A, имеющего его собственную независимую копию функционального метода "x". Принимая во внимание, что использование "прототипа" будет означать, что каждый экземпляр класса A будет использовать ту же копию метода "x".

Вот некоторый код для показа этого тонкого различия:

// x is a method assigned to the object using "this"
var A = function () {
    this.x = function () { alert('A'); };
};
A.prototype.updateX = function( value ) {
    this.x = function() { alert( value ); }
};

var a1 = new A();
var a2 = new A();
a1.x();  // Displays 'A'
a2.x();  // Also displays 'A'
a1.updateX('Z');
a1.x();  // Displays 'Z'
a2.x();  // Still displays 'A'

// Here x is a method assigned to the object using "prototype"
var B = function () { };
B.prototype.x = function () { alert('B'); };

B.prototype.updateX = function( value ) {
    B.prototype.x = function() { alert( value ); }
}

var b1 = new B();
var b2 = new B();
b1.x();  // Displays 'B'
b2.x();  // Also displays 'B'
b1.updateX('Y');
b1.x();  // Displays 'Y'
b2.x();  // Also displays 'Y' because by using prototype we have changed it for all instances

, Поскольку другие упомянули, существуют различные причины выбрать один метод или другой. Мой образец просто предназначен для ясной демонстрации различия.

230
ответ дан kaiser 10 October 2015 в 17:19
поделиться

Основная проблема с использованием this вместо prototype состоит в том, что при переопределении метода конструктор базового класса будет по-прежнему ссылаться на переопределенный метод. Подумайте над этим:

BaseClass = function() {
    var text = null;

    this.setText = function(value) {
        text = value + " BaseClass!";
    };

    this.getText = function() {
        return text;
    };

    this.setText("Hello"); // This always calls BaseClass.setText()
};

SubClass = function() {
    // setText is not overridden yet,
    // so the constructor calls the superclass' method
    BaseClass.call(this);

    // Keeping a reference to the superclass' method
    var super_setText = this.setText;
    // Overriding
    this.setText = function(value) {
        super_setText.call(this, "SubClass says: " + value);
    };
};
SubClass.prototype = new BaseClass();

var subClass = new SubClass();
console.log(subClass.getText()); // Hello BaseClass!

subClass.setText("Hello"); // setText is already overridden
console.log(subClass.getText()); // SubClass says: Hello BaseClass!

против:

BaseClass = function() {
    this.setText("Hello"); // This calls the overridden method
};

BaseClass.prototype.setText = function(value) {
    this.text = value + " BaseClass!";
};

BaseClass.prototype.getText = function() {
    return this.text;
};

SubClass = function() {
    // setText is already overridden, so this works as expected
    BaseClass.call(this);
};
SubClass.prototype = new BaseClass();

SubClass.prototype.setText = function(value) {
    BaseClass.prototype.setText.call(this, "SubClass says: " + value);
};

var subClass = new SubClass();
console.log(subClass.getText()); // SubClass says: Hello BaseClass!

Если вы считаете, что это не проблема, то это зависит от того, можете ли вы жить без личных переменных, и достаточно ли у вас опыта) знать утечку, когда вы видите один. Кроме того, неудобно помещать логику конструктора после определения метода.

var A = function (param1) {
    var privateVar = null; // Private variable

    // Calling this.setPrivateVar(param1) here would be an error

    this.setPrivateVar = function (value) {
        privateVar = value;
        console.log("setPrivateVar value set to: " + value);

        // param1 is still here, possible memory leak
        console.log("setPrivateVar has param1: " + param1);
    };

    // The constructor logic starts here possibly after
    // many lines of code that define methods

    this.setPrivateVar(param1); // This is valid
};

var a = new A(0);
// setPrivateVar value set to: 0
// setPrivateVar has param1: 0

a.setPrivateVar(1);
//setPrivateVar value set to: 1
//setPrivateVar has param1: 0

и

var A = function (param1) {
    this.setPublicVar(param1); // This is valid
};
A.prototype.setPublicVar = function (value) {
    this.publicVar = value; // No private variable
};

var a = new A(0);
a.setPublicVar(1);
console.log(a.publicVar); // 1
.
21
ответ дан tarkabak 10 October 2015 в 17:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: