2014-02-04 5 views
0

Каковы преимущества размещения материала на прототипе объекта? Например, эти две реализации ChessPiece кажутся очень похожими. Каковы компромиссы?Зачем ставить метод на прототипе объекта?

Без прототипа

var ChessPiece = function(x, y) { 
    var self = this; 
    this.x = x; 
    this.y = y; 
    this.getNotation = function() { 
    return 'abcdefgh'[self.x] + '12345678'[self.y]; 
    };  
} 

var pawn1 = new ChessPiece(1, 0); 
pawn1.getNotation(); // 'b1'; 

С прототипом

var ChessPiece = function(x, y) { 
    this.x = x; 
    this.y = y; 
} 

ChessPiece.prototype.getNotation = function() { 
    return 'abcdefgh'[this.x] + '12345678'[this.y]; 
} 

var pawn2 = new ChessPiece(1, 1); 
pawn2.getNotation(); // 'b2' 

Для меня наиболее существенная разница в том, что, когда getNotation на прототипе ChessPiece «s, этот метод разделяет все экземпляров. Когда это не на прототипе, есть несколько копий getNotation. Это имеет значение? Я больше не хватает?

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

+3

Добавление метода к прототипу заставляет все экземпляры совместно использовать эту функцию для своего свойства. В противном случае вы создаете новую (другую) функцию для каждого экземпляра и назначаете ее как свойство. Кроме того, настройка свойства внутри конструктора дает доступ к «приватным» переменным, а также истинному «этому» экземпляра, если он выполняется правильно; прототипы не имеют доступа к «приватным» переменным и не гарантируют получение истинным значением этого значения this this this this this this this this – Ian

+0

еще одной информации, прочитанной: http://stackoverflow.com/questions/4736910/javascript-when-to-use -prototypes – Ian

+0

и окончательное чтение из простого поиска в Google: http://stackoverflow.com/questions/4691044/should-i-use-prototype-or-not – Ian

ответ

0

Ваш без прототипа по-своему похож на то, что Дуглас Крокфорд рекомендует в «JavaScript: Хорошие детали» с важным исключением. Его версия вашего примера может выглядеть примерно так:

var chessPiece = function(x, y) { 
    var obj = {}; 
    obj.x = x; 
    obj.y = y; 
    obj.getNotation = function() { 
    return 'abcdefgh'[obj.x] + '12345678'[obj.y]; 
    }; 
    return obj;  
} 

var pawn1 = chessPiece(1, 0); 
pawn1.getNotation(); // 'b1'; 
pawn1.x; // 1 

Крокфорд избегает «нового» оператора из-за опасности со значением «это». Кроме того, он позволяет инкапсулировать значения, которые, как правило, сложнее в JS. Например, если х и у на самом деле означает быть более частным, вы можете сделать это:

var chessPiece = function(x, y) { 
    var obj = {}; 
    var xCoord = x; 
    var yCoord = y; 
    obj.getNotation = function() { 
    return 'abcdefgh'[xCoord] + '12345678'[yCoord]; 
    }; 
    obj.moveX = function (amount) { 
    x += amount; 
    } 
    return obj;  
} 

var pawn1 = chessPiece(1, 0); 
pawn1.getNotation(); // 'b1'; 
pawn1.move(2); 
pawn1.getNotation(); // 'd1'; 
pawn1.x; // undefined 

С xCoord и yCoord оказались в ловушке в области замыкания, getNotation и MOVEX как работа с xCoord и yCoord действуют как частные переменные , У Crockford есть другие советы и применения для этой техники.

+0

Не все, что говорит Крокфорд, имеет смысл. В одном видео он утверждает, что «классическое» наследование (конструкторские функции/прототип) вы не можете использовать код конструктора родителя, когда Child наследует от родителя. Он восхваляет прототип во всем видео, а затем избегает его использования в конечном итоге, демонстрируя «лучший» шаблон, который забивает каждый член в конструкторе (вообще не используя прототип). Я бы посоветовал не выкидывать ребенка с водой для ванны и видеть, когда шаблоны будут полезны для вашего кода, и при использовании «нового» было бы более уместным, а не пытаться избежать использования нового все время. – HMR

+0

http://www.youtube.com/watch?v=ya4UHuXNygM в 50:30. Не уверен, что он троллинг здесь, потому что он продолжает говорить: «Ты все еще следишь за этим?» как бы осмеливаясь говорить на публике. Ему не нравится, как JS пытается скопировать наследование Java, а затем не нравится, как на самом деле выглядит наследование JS, потому что оно не похоже на Java-код. Не использовать Object.create (или вспомогательная функция) для создания прототипа части наследования и утверждения, что конструктор родителя нельзя использовать повторно, действительно является плохим способом реализации JS OOP – HMR

+0

Некоторые опечатки в коде - moveX должен увеличивать xCoord, а не x; и призыв к концу должен быть pawn1.moveX, а не pawn1.move. – Scott

Смежные вопросы