вопросы о прототипе в javascript [duplicate]

Самое простое решение - создать функцию JavaScript и вызвать его для обратного вызова Ajax success.

function callServerAsync(){
    $.ajax({
        url: '...',
        success: function(response) {

            successCallback(response);
        }
    });
}

function successCallback(responseObj){
    // Do something like read the response and show data
    alert(JSON.stringify(responseObj)); // Only applicable to JSON response
}

function foo(callback) {

    $.ajax({
        url: '...',
        success: function(response) {
           return callback(null, response);
        }
    });
}

var result = foo(function(err, result){
          if (!err)
           console.log(result);    
}); 
11
задан Marco Bonelli 12 October 2014 в 15:55
поделиться

6 ответов

Согласно спецификациям ECMA Script 5 ,

Значение свойства prototype используется для инициализации внутреннего свойства [[Prototype]] для вновь созданного объекта перед тем как объект Function вызывается как конструктор для этого вновь созданного объекта.

Понятно, что prototype просто инициализирует свойство [[Prototype]]. Когда мы создаем объект, [[Prototype]] устанавливается как объект prototype функции конструктора и устанавливается цепочка прототипов. В вашем случае, когда вы делаете

var obj = function() {};
obj.prototype.x = 5;

var instance1 = new obj();

, [[Prototype]] выглядит так

console.log(Object.getPrototypeOf(instance1));
# { x: 5 }

(Да, вы можете получить доступ к [[Prototype]] с помощью Object.getPrototypeOf]

Итак, когда JS Engine ищет x в instance1, он находит значение как 5, а поскольку y не определен, он использует undefined.

Во втором случае

obj.prototype = {y: 6};

var instance2 = new obj();

вы меняете объект prototype объекта obj, так что новые объекты, построенные с помощью этих функций, будут использовать новый объект, назначенный ему. Таким образом, [[Prototype]] выглядит так: instance2

console.log(Object.getPrototypeOf(instance2));
# { y: 6 }

Вот почему instance2 не смог найти в нем x, но y.

< hr>

Чтобы ответить на обновленный вопрос,

EDIT: Как я могу изменить прототип всех экземпляров?

Вы можете изменить , прототип старого объекта с Object.setPrototypeOf, как это

Object.setPrototypeOf(instance1, {
    y: 6
});

Так как это [[Prototype]] instance1 отличается от instance2, мы можем просто обновить функцию конструктора prototype, например

delete obj.prototype.x;
obj.prototype.y = 6;

Теперь мы не изменили внутреннего свойства как instance1, так и instance2. Мы можем проверить, что так

console.log(Object.getPrototypeOf(instance1) === Object.getPrototypeOf(instance2));
# true
console.log(Object.getPrototypeOf(instance1) === obj.prototype);
# true

Примечание: Соглашение должно называть функции-конструкторы с начальной буквой заглавной буквой.

5
ответ дан thefourtheye 1 September 2018 в 01:01
поделиться

Поскольку instance1 уже создан. Ключевое слово new создает новый объект, выполняя функцию-конструктор, которая в вашем случае obj.

Поскольку вы изменили прототип после инициализации первого экземпляра, вы больше не имеете того же состояния (например, прототип) конструктора и не можете создать тот же объект. Но созданные все еще существуют, ссылаясь на старый прототип.

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

Изменить: # 4 Эта скрипка: http://jsfiddle.net/doy3g1fh/ показывает, что

obj.prototype.y=6

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

0
ответ дан Nikola Geneshki 1 September 2018 в 01:01
поделиться

Прототип экземпляров не ссылается на класс, вместо этого они ссылаются на сам объект-прототип. Это станет ясным, когда вы попробуете Object.getPrototypeOf(), чтобы увидеть, какой прототип-объект ссылается на экземпляр.

Object.getPrototypeOf(instance1)
Object { x: 5, 1 more… }

Object.getPrototypeOf(instance2)
Object { y: 6 }

Это поле getPrototypeOf ссылки должно быть внутренним, которое существует для каждого экземпляра. До getPrototypeOf существовало, вы можете получить это через __proto__.

1
ответ дан simonzack 1 September 2018 в 01:01
поделиться
  1. Почему этот журнал 5, undefined, undefined, 6 вместо undefined, 6, undefined, 6?
  2. Почему замена прототипа не меняет прототип всех экземпляров объекта, как это обычно бывает?

По сути, это сводится к тому, что ссылки на объекты - это значения, а скорее числа, которые указывают механизм JavaScript (V8 в вашем случае), где объект находится в памяти. Когда вы копируете значение, вы делаете именно это: вы копируете значение. Копирование ссылки на объект делает копию ссылки (а не объекта) и никоим образом не связывает место назначения этого значения с источником значения больше, чем это связывает b с a:

var a = 5;
var b = a;
a = 6;
console.log(b, a); // 5, 6

Итак, ваш код регистрирует то, что он регистрирует, и не изменяет прототип instance1, по той же причине этот код записывает то же самое и не меняет значение instance1.p:

var foo = {x: 5};
var instance1 = {p: foo};

foo = {y: 6};

var instance2 = {p: foo};

console.log(instance1.p.x, instance1.p.y, instance2.p.x, instance2.p.y);

Давайте набросим на него некоторое ASCII-искусство (ну, Unicode-art), которое также ответит:

  1. Что делает двигатель V8, шаг за шагом, в этом коде?

После запуска этого:

var obj = function() {};
obj.prototype.x = 5;

var instance1 = new obj();

... у вас есть что-то примерно так в памяти (игнорируя некоторые детали):

                 +−−−−−−−−−−−−−−−−−−−−−+             
                 |     (function)      |             
                 +−−−−−−−−−−−−−−−−−−−−−+             
obj<Ref55461>−−−>| prototype<Ref32156> |−−−−−−−−−−−+
                 +−−−−−−−−−−−−−−−−−−−−−+            \ 
                                                     \     
                                                      \    
                                                       \   +−−−−−−−−−−+
                                                        +−>| (object) |
                                                       /   +−−−−−−−−−−+
                                                      /    | x<5>     |
                      +−−−−−−−−−−−−−−−−−−−−−−−−−+    /     +−−−−−−−−−−+
                      |         (object)        |   /
                      +−−−−−−−−−−−−−−−−−−−−−−−−−+  /
instance1<Ref86545>−−>| [[Prototype]]<Ref32156> |−+
                      +−−−−−−−−−−−−−−−−−−−−−−−−−+

Поскольку ссылки на объекты являются значениями, а присваивание всегда копирует значения , когда V8 (или любой другой движок) создает instance1, он копирует значение из obj.prototype (показано здесь концептуально как <Ref32156>) на внутренний слот instance1 [[Prototype]].

Тогда, когда вы делаете

obj.prototype = {y: 6};

... вы меняете значение в obj.prototype (показано здесь как изменение <Ref32156> на <Ref77458>), но это не влияет на значение (<Ref32156> ]) в слоте instance1 [[Prototype]]:

                 +−−−−−−−−−−−−−−−−−−−−−+                   
                 |     (function)      |                   
                 +−−−−−−−−−−−−−−−−−−−−−+                   +−−−−−−−−−−+
obj<Ref55461>−−−>| prototype<Ref77458> |−−−−−−−−−−−−−−−−−−>| (object) |
                 +−−−−−−−−−−−−−−−−−−−−−+                   +−−−−−−−−−−+
                                                           | y<6>     |
                                                           +−−−−−−−−−−+

                                                           +−−−−−−−−−−+
                                                        +−>| (object) |
                                                       /   +−−−−−−−−−−+
                                                      /    | x<5>     |
                      +−−−−−−−−−−−−−−−−−−−−−−−−−+    /     +−−−−−−−−−−+
                      |         (object)        |   /
                      +−−−−−−−−−−−−−−−−−−−−−−−−−+  /
instance1<Ref86545>−−>| [[Prototype]]<Ref32156> |−+
                      +−−−−−−−−−−−−−−−−−−−−−−−−−+

... и поэтому, когда вы делаете

var instance2 = new obj();

... у вас есть:

                 +−−−−−−−−−−−−−−−−−−−−−+                   
                 |     (function)      |                   
                 +−−−−−−−−−−−−−−−−−−−−−+                   +−−−−−−−−−−+
obj<Ref55461>−−−>| prototype<Ref77458> |−−−−−−−−−−−−−−−−+−>| (object) |
                 +−−−−−−−−−−−−−−−−−−−−−+               /   +−−−−−−−−−−+
                                                      /    | y<6>     |
                      +−−−−−−−−−−−−−−−−−−−−−−−−−+    /     +−−−−−−−−−−+
                      |         (object)        |   /      
                      +−−−−−−−−−−−−−−−−−−−−−−−−−+  /       
instance2<Ref98465>−−>| [[Prototype]]<Ref77458> |−+        +−−−−−−−−−−+
                      +−−−−−−−−−−−−−−−−−−−−−−−−−+       +−>| (object) |
                                                       /   +−−−−−−−−−−+
                                                      /    | x<5>     |
                      +−−−−−−−−−−−−−−−−−−−−−−−−−+    /     +−−−−−−−−−−+
                      |         (object)        |   /
                      +−−−−−−−−−−−−−−−−−−−−−−−−−+  /
instance1<Ref86545>−−>| [[Prototype]]<Ref32156> |−+
                      +−−−−−−−−−−−−−−−−−−−−−−−−−+

... что объясняет результат console.log.

  1. EDIT: Как мне пойти на смену прототипа всех экземпляров?

Если вы хотите фактически изменить какой объект, который они используют в качестве своего прототипа, вы можете сделать это только в том случае, если у вас есть ссылка на экземпляр (ы), который вы хотите изменить, и только на JavaScript-движке, поддерживающем функции ES2015, с помощью Object.setPrototypeOf или (в среде веб-браузера, и если объект в конечном итоге наследуется от Object.prototype) через аксессуар __proto__ свойство (не рекомендуется):

Object.setPrototypeOf(instance1, obj.prototype);

setPrototypeOf изменяет значение внутреннего слота [[Prototype]] в объекте (как и установка __proto__, если объект имеет его) .

Вы не можете этого сделать, если у вас нет ac

Я не думаю, что вы это делаете, учитывая этот вопрос, но если вы просто хотите изменить состояние объекта, который они используют в качестве своего прототипа (возможно, добавив y), вы можете, конечно, просто установить на нем свойства, а так как прототипное наследование JavaScript является «живым» (есть прямая ссылка на прототип из экземпляра), вы можете затем получить доступ к этим свойствам в любом экземпляре, который наследуется от прототипа, даже если они были созданы до того, как вы внесли изменение:

var Example = function() { };
Example.prototype.x = 5;

var instance1 = new Example();
console.log(instance1.x, instance1.y); // 5, undefined

Example.prototype.y = 6;
console.log(instance1.x, instance1.y); // 5, 6
2
ответ дан T.J. Crowder 1 September 2018 в 01:01
поделиться
Прототип

- это функция, которая сочетается с новыми за кулисами. Он применяется ко всем экземплярам этой функции, используемой с новым. В первом примере вы добавляете .x = 5 к прототипу, а созданный экземпляр имеет значение .x = 5 в качестве значения. Позже вы модифицируете прототип для нового объекта. Теперь это прототип, который используется в любых новых экземплярах. Вот почему первый экземпляр имеет .x = 5, а второй имеет только .y = 6

1
ответ дан Travis J 1 September 2018 в 01:01
поделиться

Объяснение

Итак, во-первых, ваши две строки кода создают функцию obj и назначают ее прототипу {x: 5}.

Когда вы создаете экземпляр этого объект, он, по-видимому, имеет внутреннюю ссылку на прототип, который существовал, когда он был new 'd.

. После этого вы переназначите прототип на {y: 6}, который не влияет на внутренний instance1 ссылка на первый прототип.

Затем, когда вы создаете instance2, он имеет внутреннюю ссылку на 2-й прототип, и поэтому запись в них приведет к 5, undefined, undefined, 6.

# 4

Вы могли бы вместо переназначения прототипа новому объекту:

obj.prototype = {y: 6};

Изменить вместо этого прототип:

delete obj.prototype.x; // Setting to undefined should produce same behaviour
obj.prototype.y = 6;

Это приведет к выходу: undefined, 6, undefined, 6

Я тестировал это с помощью http://jsfiddle.net/9j3260gp/ в последних версиях Chrome и Firefox в Windows.

9
ответ дан Winestone 1 September 2018 в 01:01
поделиться
Другие вопросы по тегам:

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