Может ли классы/объекты JavaScript иметь конструкторы? Как они созданы?Конструкторы в объектах JavaScript
ответ
Использование прототипов:
function Box(color) // Constructor
{
this.color = color;
}
Box.prototype.getColor = function()
{
return this.color;
};
Скрытие "цвет" (несколько напоминает закрытую переменную):
function Box(col)
{
var color = col;
this.getColor = function()
{
return color;
};
}
Использование:
var blueBox = new Box("blue");
alert(blueBox.getColor()); // will alert blue
var greenBox = new Box("green");
alert(greenBox.getColor()); // will alert green
Спасибо :). –
Нужно ли префикс для всех полей-членов «это». внутри объекта, или это только потому, что элемент назван так же, как параметр конструктора (цвет)? –
@BorisB, да, вы это делаете - это определяет цвет и getColor на объекте Box, иначе вы назначаете переменные в обычной области. – Nick
Вот шаблон, который я иногда использую для ООП-подобного поведения в JavaScript. Как вы можете видеть, вы можете имитировать частные (как статические, так и экземпляры) члены, используя закрытие. То, что возвращает new MyClass()
, является объектом с только свойствами, назначенными объекту this
, и в объекте prototype
«класса».
var MyClass = (function() {
// private static
var nextId = 1;
// constructor
var cls = function() {
// private
var id = nextId++;
var name = 'Unknown';
// public (this instance only)
this.get_id = function() { return id; };
this.get_name = function() { return name; };
this.set_name = function (value) {
if (typeof value != 'string')
throw 'Name must be a string';
if (value.length < 2 || value.length > 20)
throw 'Name must be 2-20 characters long.';
name = value;
};
};
// public static
cls.get_nextId = function() {
return nextId;
};
// public (shared across instances)
cls.prototype = {
announce: function() {
alert('Hi there! My id is ' + this.get_id() + ' and my name is "' + this.get_name() + '"!\r\n' +
'The next fellow\'s id will be ' + MyClass.get_nextId() + '!');
}
};
return cls;
})();
Я спросил о наследовании, используя эту модель, так что здесь идет:
// It's a good idea to have a utility class to wire up inheritance.
function inherit(cls, superCls) {
// We use an intermediary empty constructor to create an
// inheritance chain, because using the super class' constructor
// might have side effects.
var construct = function() {};
construct.prototype = superCls.prototype;
cls.prototype = new construct;
cls.prototype.constructor = cls;
cls.super = superCls;
}
var MyChildClass = (function() {
// constructor
var cls = function (surName) {
// Call super constructor on this instance (any arguments
// to the constructor would go after "this" in call(…)).
this.constructor.super.call(this);
// Shadowing instance properties is a little bit less
// intuitive, but can be done:
var getName = this.get_name;
// public (this instance only)
this.get_name = function() {
return getName.call(this) + ' ' + surName;
};
};
inherit(cls, MyClass); // <-- important!
return cls;
})();
И пример, чтобы использовать его все:
var bob = new MyClass();
bob.set_name('Bob');
bob.announce(); // id is 1, name shows as "Bob"
var john = new MyChildClass('Doe');
john.set_name('John');
john.announce(); // id is 2, name shows as "John Doe"
alert(john instanceof MyClass); // true
Как вы можете видеть, классы правильно взаимодействуют друг с другом (они разделяют статический идентификатор от MyClass
, метод announce
использует правильный метод get_name
и т. д.)
Следует отметить необходимость скрывать свойства экземпляра. Фактически вы можете сделать функцию inherit
пройденной через все свойства экземпляра (используя hasOwnProperty
), которые являются функциями, и автоматически добавить свойство super_<method name>
. Это позволит вам позвонить this.super_get_name()
вместо того, чтобы хранить его во временном значении и называть его связанным, используя call
.
Для методов прототипа вам не нужно беспокоиться об этом, но если вы хотите получить доступ к методам прототипов суперкласса, вы можете просто позвонить this.constructor.super.prototype.methodName
. Если вы хотите сделать это менее подробным, вы можете, конечно, добавить удобства. :)
Просто примечание о части 'cls.prototype':« shared through instance »предназначено только для чтения значения (вызов' announce'). Если вы установите 'myClassInstance.announce' на другое значение, оно создаст новое свойство в' myClassInstance', поэтому оно применимо только к этому объекту, а не к другим экземплярам класса. Присвоение 'MyClass.prototype.announce' будет влиять на все экземпляры. –
@Blixt - широко использовали ваш пример - спасибо! –
Без проблем, рад помочь! :) – Blixt
So what is the point of "constructor" property? Cannot figure out where it could be useful, any ideas?
Точка свойства конструктора является условием какой-то способ притворяться, что JavaScript имеет классы. Одна из вещей, которую вы не может полезно сделать, это изменить конструктор объекта после его создания. Это сложно.
я написал достаточно полный кусок на нем несколько лет назад: http://joost.zeekat.nl/constructors-considered-mildly-confusing.html
Привет! Спасибо за статью. Теперь это более ясно. – igor
Дело в том, чтобы использовать «новое» ключевое слово. «d = new Drofto()» создает пустой объект и запускает функцию Drofto с указанным новым объектом, ограниченным как «это». Функция Drofto может свободно возвращать что-либо, но обычно принято возвращать что-то, что считается членом класса Drofto. –
Используя образец Ники выше, вы можете создать конструктор для объектов без параметров, используя оператор возврата в качестве последнего оператора в вашем определении объекта ,Верните функцию конструктора, как показано ниже, и она будет работать код в __construct каждый раз, когда вы создаете объект:
function Box()
{
var __construct = function() {
alert("Object Created.");
this.color = 'green';
}
this.color = '';
this.getColor = function() {
return this.color;
}
__construct();
}
var b = new Box();
Вы не возвращаете функцию конструктора, вы просто вызываете ее. –
Если вы попытаетесь использовать 'this.getColor();' в строке выше 'alert (" Object Created. ");' Ничего не будет предупреждено. Будет ошибка, например, «getColor не определен». Если вы хотите, чтобы конструкция имела возможность вызвать другие методы в объекте, она должна быть определена после всех других методов. Поэтому вместо вызова '__construct();' в последней строке просто определите конструкцию там и поместите '()' после нее, чтобы принудительно ее выполнить. – thinsoldier
Коррекция. Добавление '()' в конец определения __construct все еще приводило к ошибке. Я должен был вызвать '__construct();' в своей строке, как в исходном коде, чтобы избежать ошибки. – thinsoldier
Это конструктор:
function MyClass() {}
Когда вы
var myObj = new MyClass();
MyClass
, и новый объект возвращается этому классу.
Чтобы уточнить, что это значит, наверху вашего класса вы можете сказать 'alert (valuePassedInAsArgument);' и это будет выполняться один раз для каждого экземпляра, поэтому весь класс является самим конструктором. –
'новый объект возвращается этому классу' - не похоже ли на новый объект этой функции? – mmcrae
в функциях javascript являются объектами – leonziyo
Я думаю, что опубликую, что я делаю с закрытием javascript, так как никто пока не использует закрытие.
var user = function(id) {
// private properties & methods goes here.
var someValue;
function doSomething(data) {
someValue = data;
};
// constructor goes here.
if (!id) return null;
// public properties & methods goes here.
return {
id: id,
method: function(params) {
doSomething(params);
}
};
};
Комментарии и предложения к этому решению приветствуются. :)
Пара комментариев: 1) утверждение if (! Id) небезопасно, значения, такие как 0 или false, заставят его оценивать true и возвращать null. Я предполагаю, что вы хотите проверить undefined или null, в этом случае === null и === undefined будет лучше. 2) Это более похоже на шаблон модуля (http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth) по сравнению с конструктором, причем разница заключается в том, что модуль возвращает объект из функции, тогда как конструктор создает объект в паре с новым ключевым словом, и в этом случае вы будете устанавливать значения «this» вместо объекта. – Rich
Мне кажется, что большинство из вас дает пример геттеров и сеттеров не конструктор, то есть http://en.wikipedia.org/wiki/Constructor_(object-oriented_programming).
lunched-dan был ближе, но пример не работал в jsFiddle.
В этом примере создается функция частного конструктора, которая работает только во время создания объекта.
var color = 'black';
function Box()
{
// private property
var color = '';
// private constructor
var __construct = function() {
alert("Object Created.");
color = 'green';
}()
// getter
this.getColor = function() {
return color;
}
// setter
this.setColor = function(data) {
color = data;
}
}
var b = new Box();
alert(b.getColor()); // should be green
b.setColor('orange');
alert(b.getColor()); // should be orange
alert(color); // should be black
Если вы хотите, чтобы назначить общие свойства, то конструктор может быть определен как таковой:
var color = 'black';
function Box()
{
// public property
this.color = '';
// private constructor
var __construct = function(that) {
alert("Object Created.");
that.color = 'green';
}(this)
// getter
this.getColor = function() {
return this.color;
}
// setter
this.setColor = function(color) {
this.color = color;
}
}
var b = new Box();
alert(b.getColor()); // should be green
b.setColor('orange');
alert(b.getColor()); // should be orange
alert(color); // should be black
Как это не ответ # 1? Только Джон создал конструктор с параметрами. – Rap
Есть ли способ получить пример наследования с использованием этой парадигмы для конструкторов? –
В чем причина того, что здесь есть частный конструктор? –
Эта модель хорошо служил мне. С помощью этого шаблона вы создаете классы в отдельных файлах, загружаете их в свое общее приложение «по мере необходимости».
// Namespace
// (Creating new if not instantiated yet, otherwise, use existing and just add to it)
var myApp = myApp || {};
// "Package"
// Similar to how you would establish a package in other languages
(function() {
// "Class"
var MyClass = function(params) {
this.initialize(params);
}
// "Private Static" vars
// - Only accessible to functions in this class.
// - Doesn't get wiped out when we create a new instance.
var countInstances = 0;
var allInstances = [];
// "Private Static" functions
// - Same as above, but it's a function accessible
// only to other functions in this class.
function doSomething(){
}
// "Public Static" vars
// - Everyone has access.
// - Doesn't get wiped out when we create a new instance.
MyClass.counter = 0;
// "Public Static" functions
// - Same as above, but anyone can call this "static method".
// - Kinda like a singleton class situation.
MyClass.foobar = function(){
}
// Public properties and methods are built into the "prototype"
// - This is how each instance can become unique unto itself.
// - Establishing "p" as "local" (Static Private) variable
// simply so we don't have to keep typing "MyClass.prototype"
// for each property and function.
var p = MyClass.prototype;
// "Public" vars
p.id = null;
p.firstname = null;
p.lastname = null;
// "Private" vars
// - Only used by "this" instance.
// - There isn't "true" privacy for each
// instance so we have to fake it.
// - By tradition, we indicate "privacy"
// by prefixing it with an underscore.
// - So technically, anyone can access, but we simply
// don't tell anyone about it (e.g. in your API)
// so no one knows about it :)
p._foo = null;
p.initialize = function(params){
this.id = MyClass.counter++;
this.firstname = params.firstname;
this.lastname = params.lastname;
MyClass.counter++;
countInstances++;
allInstances.push(this);
}
p.doAlert = function(theMessage){
alert(this.firstname + " " + this.lastname + " said: " + theMessage + ". My id:" + this.id + ". Total People:" + countInstances + ". First Person:" + allInstances[0].firstname + " " + allInstances[0].lastname);
}
// Assign class to app
myApp.MyClass = MyClass;
// Close the "Package"
}());
// Usage example:
var bob = new myApp.MyClass({ firstname : "bob",
lastname : "er"
});
bob.doAlert("hello there");
Это переменные экземпляра, но они имеют «общедоступную» доступность, а не «частную», как в C++ или Java. – Potatoswatter
Как бы вы хотели создать частную переменную (в классическом смысле), относящуюся к экземпляру, но не общую для всех экземпляров? – bob
См. Сайт [Douglas Crockford] (http://crockford.net), он один из разработчиков языка и главный авторитет. Я не всегда следую его шаблонам, но, как правило, частная переменная является локальным «var» в конструкторе (или аргументе функции, или в функции, подобной конструктору). – Potatoswatter
Я нашел этот учебник очень полезным. Этот подход используется большинством плагинов jQuery.
var Class = function(methods) {
var klass = function() {
this.initialize.apply(this, arguments);
};
for (var property in methods) {
klass.prototype[property] = methods[property];
}
if (!klass.prototype.initialize) klass.prototype.initialize = function(){};
return klass;
};
Теперь
var Person = Class({
initialize: function(name, age) {
this.name = name;
this.age = age;
},
toString: function() {
return "My name is "+this.name+" and I am "+this.age+" years old.";
}
});
var alice = new Person('Alice', 26);
alert(alice.name); //displays "Alice"
alert(alice.age); //displays "26"
alert(alice.toString()); //displays "My name is Alice and I am 26 years old" in most browsers.
//IE 8 and below display the Object's toString() instead! "[Object object]"
Я сжимаю всякий раз, когда вижу людей, использующих «класс» – Madbreaks
Пример здесь: http://jsfiddle.net/FZ5nC/
Попробуйте этот шаблон:
<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Name = Name||{};
Name.Space = Name.Space||{};
//============================================================
// Constructor - MUST BE AT TOP OF FILE
//------------------------------------------------------------
Name.Space.ClassName = function Name_Space_ClassName(){}
//============================================================
// Member Functions & Variables
//------------------------------------------------------------
Name.Space.ClassName.prototype = {
v1: null
,v2: null
,f1: function Name_Space_ClassName_f1(){}
}
//============================================================
// Static Variables
//------------------------------------------------------------
Name.Space.ClassName.staticVar = 0;
//============================================================
// Static Functions
//------------------------------------------------------------
Name.Space.ClassName.staticFunc = function Name_Space_ClassName_staticFunc(){
}
</script>
Вы должны отрегулировать лет ур пространства имен, если вы определяете статический класс:
<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Shape = Shape||{};
Shape.Rectangle = Shape.Rectangle||{};
// In previous example, Rectangle was defined in the constructor.
</script>
Пример Класс:
<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Shape = Shape||{};
//============================================================
// Constructor - MUST BE AT TOP OF FILE
//------------------------------------------------------------
Shape.Rectangle = function Shape_Rectangle(width, height, color){
this.Width = width;
this.Height = height;
this.Color = color;
}
//============================================================
// Member Functions & Variables
//------------------------------------------------------------
Shape.Rectangle.prototype = {
Width: null
,Height: null
,Color: null
,Draw: function Shape_Rectangle_Draw(canvasId, x, y){
var canvas = document.getElementById(canvasId);
var context = canvas.getContext("2d");
context.fillStyle = this.Color;
context.fillRect(x, y, this.Width, this.Height);
}
}
//============================================================
// Static Variables
//------------------------------------------------------------
Shape.Rectangle.Sides = 4;
//============================================================
// Static Functions
//------------------------------------------------------------
Shape.Rectangle.CreateSmallBlue = function Shape_Rectangle_CreateSmallBlue(){
return new Shape.Rectangle(5,8,'#0000ff');
}
Shape.Rectangle.CreateBigRed = function Shape_Rectangle_CreateBigRed(){
return new Shape.Rectangle(50,25,'#ff0000');
}
</script>
Пример конкретизации:
<canvas id="painting" width="500" height="500"></canvas>
<script>
alert("A rectangle has "+Shape.Rectangle.Sides+" sides.");
var r1 = new Shape.Rectangle(16, 12, "#aa22cc");
r1.Draw("painting",0, 20);
var r2 = Shape.Rectangle.CreateSmallBlue();
r2.Draw("painting", 0, 0);
Shape.Rectangle.CreateBigRed().Draw("painting", 10, 0);
</script>
функции Примечание определяются как A.B = функция a_b(). Это упрощает отладку вашего сценария.Открыть в Chrome Осмотрите панель Element, запустите этот сценарий, и расширить отладки трассировки:
<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Fail = Fail||{};
//============================================================
// Static Functions
//------------------------------------------------------------
Fail.Test = function Fail_Test(){
A.Func.That.Does.Not.Exist();
}
Fail.Test();
</script>
При использовании большого шаблона Blixt от выше, я узнал, что это не очень хорошо работает с Наследованием многоуровневого (MyGrandChildClass проходящее MyChildClass расширяя MyClass) - он циклически вызывает вызов конструктора первого родителя снова и снова. Так вот простое решение - если вам нужно наследование многоуровневого, вместо того, чтобы использовать this.constructor.super.call(this, surName);
использовать chainSuper(this).call(this, surName);
с функцией цепи, определенной как это:
function chainSuper(cls) {
if (cls.__depth == undefined) cls.__depth = 1; else cls.__depth++;
var depth = cls.__depth;
var sup = cls.constructor.super;
while (depth > 1) {
if (sup.super != undefined) sup = sup.super;
depth--;
}
return sup;
}
Они делают, если вы используете Typescript - с открытым исходным кодом от MicroSoft :-)
class BankAccount {
balance: number;
constructor(initially: number) {
this.balance = initially;
}
deposit(credit: number) {
this.balance += credit;
return this.balance;
}
}
Typcript позволяет создавать фальшивые конструкты OO, которые скомпилированы в конструкции javascript. Если вы начинаете большой проект, это может сэкономить вам много времени, и он просто достиг версии 1.0.
http://www.typescriptlang.org/Content/TypeScript%20Language%20Specification.pdf
Приведенный выше код получает 'скомпилированных' в:
var BankAccount = (function() {
function BankAccount(initially) {
this.balance = initially;
}
BankAccount.prototype.deposit = function (credit) {
this.balance += credit;
return this.balance;
};
return BankAccount;
})();
Я работаю над большим проектом, и я пытаюсь убедить людей, что TypeScript даст нам бегущую стрельбу. Посмотрим, как это получится. – wootscootinboogie
@wootscootinboogie В один день (заканчивается в 5:30 утра) У меня довольно далеко и довольно удобно. Я настоятельно рекомендую прочесть спецификацию, и, хотя вы можете пропустить половину реальных мелочей, вы делаете себе одолжение, прочитывая ее хотя бы один раз. видео этого парня отличные https://www.youtube.ком/пользователь/basaratali/видео. удачи) –
http://www.jsoops.net/ довольно хорошо для ЛСГ в Js. Если вы предоставляете частную, защищенную, общедоступную переменную и функцию, а также функцию наследования. Пример кода:
var ClassA = JsOops(function (pri, pro, pub)
{// pri = private, pro = protected, pub = public
pri.className = "I am A ";
this.init = function (var1)// constructor
{
pri.className += var1;
}
pub.getData = function()
{
return "ClassA(Top=" + pro.getClassName() + ", This=" + pri.getClassName()
+ ", ID=" + pro.getClassId() + ")";
}
pri.getClassName = function() { return pri.className; }
pro.getClassName = function() { return pri.className; }
pro.getClassId = function() { return 1; }
});
var newA = new ClassA("Class");
//***Access public function
console.log(typeof (newA.getData));
// function
console.log(newA.getData());
// ClassA(Top=I am A Class, This=I am A Class, ID=1)
//***You can not access constructor, private and protected function
console.log(typeof (newA.init)); // undefined
console.log(typeof (newA.className)); // undefined
console.log(typeof (newA.pro)); // undefined
console.log(typeof (newA.getClassName)); // undefined
просто для того, чтобы предложить некоторые разновидности. ds.oop - хороший способ объявить классы с конструкторами в javascript. Он поддерживает все возможные типы наследования (включая 1 тип, который даже не поддерживает C#), а также интерфейсы, которые хороши.
var Color = ds.make.class({
type: 'Color',
constructor: function (r,g,b) {
this.r = r; /* now r,g, and b are available to */
this.g = g; /* other methods in the Color class */
this.b = b;
}
});
var red = new Color(255,0,0); // using the new keyword to instantiate the class
В большинстве случаев вам необходимо как-то объявить требуемое свойство, прежде чем вы сможете вызвать метод, который передает эту информацию. Если вам не нужно сначала устанавливать свойство, вы можете просто вызвать метод внутри объекта, например. Наверное, это не самый красивый способ сделать это, но это все еще работает.
var objectA = {
color: '';
callColor : function(){
console.log(this.color);
}
this.callColor();
}
var newObject = new objectA();
В JavaScript тип вызова определяет поведение функции:
- Прямой вызов
func()
- вызов метода на объекте
obj.func()
- Конструктор вызов
new func()
- Непрямой вызова
func.call()
илиfunc.apply()
Функция вызывается как конструктор при вызове с помощью new
оператора:
function Cat(name) {
this.name = name;
}
Cat.prototype.getName = function() {
return this.name;
}
var myCat = new Cat('Sweet'); // Cat function invoked as a constructor
Любой экземпляр или объект-прототип в JavaScript имеют свойство constructor
, которая относится к функции конструктора ,
Проверьте this post о собственности объекта недвижимости.
Может быть, это стало немного проще, но ниже того, что я придумал сейчас в 2017 году:
class obj {
constructor(in_shape, in_color){
this.shape = in_shape;
this.color = in_color;
}
getInfo(){
return this.shape + ' and ' + this.color;
}
setShape(in_shape){
this.shape = in_shape;
}
setColor(in_color){
this.color = in_color;
}
}
При использовании класса выше, я следующее:
var newobj = new obj('square', 'blue');
//Here, we expect to see 'square and blue'
console.log(newobj.getInfo());
newobj.setColor('white');
newobj.setShape('sphere');
//Since we've set new color and shape, we expect the following: 'sphere and white'
console.log(newobj.getInfo());
Как вы можете видеть, конструктор Tak es в двух параметрах, и мы устанавливаем свойства объекта. Мы также изменяем цвет и форму объекта с помощью функций setter
и доказываем, что его изменение оставалось после вызова getInfo()
после этих изменений.
Немного поздно, но я надеюсь, что это поможет. Я тестировал это с модульным тестированием mocha
, и он работает хорошо.
Здесь мы должны заметить одну точку в java-скрипте, но это язык без классов, но мы можем достичь этого, используя функции в java-скрипте. Наиболее распространенным способом для достижения этой цели нам необходимо создать функцию в Java Script и использовать новыйключевое слово создать объект и использовать этотключевое слово определить свойство и methods.Below является примером.
// Function constructor
var calculator=function(num1 ,num2){
this.name="This is function constructor";
this.mulFunc=function(){
return num1*num2
};
};
var objCal=new calculator(10,10);// This is a constructor in java script
alert(objCal.mulFunc());// method call
alert(objCal.name);// property call
//Constructors With Prototypes
var calculator=function(){
this.name="Constructors With Prototypes";
};
calculator.prototype.mulFunc=function(num1 ,num2){
return num1*num2;
};
var objCal=new calculator();// This is a constructor in java script
alert(objCal.mulFunc(10,10));// method call
alert(objCal.name); // property call
- 1. Конструкторы на сгенерированных объектах с платформой Entity
- 2. JavaScript-конструкторы
- 3. Цепочки-конструкторы в JavaScript
- 4. Конструкторы в javascript
- 5. javascript функции в объектах
- 6. Равенство в объектах javascript?
- 7. Конструкторы и прототипы в javascript
- 8. Динамически модифицирующие конструкторы в JavaScript?
- 9. прототипирования с Javascript Конструкторы
- 10. Scala.js родной Конструкторы Javascript
- 11. Цепочка Javascript Конструкторы
- 12. Использование переменных в объектах Javascript
- 13. Javascript: групповые данные в объектах
- 14. простых JavaScript, функции в объектах
- 15. Вопрос о объектах javascript
- 16. Javascript - об объектах
- 17. javascript: почему нет ключей в объектах javascript
- 18. JavaScript наследование прототипов и конструкторы
- 19. Основные конструкторы - начальный уровень Javascript
- 20. JavaScript Объекты, конструкторы, точечные обозначения
- 21. JavaScript объект Конструкторы возвращают свойства
- 22. Анимация Javascript на объектах Canvas и Javascript
- 23. Полиморфизм в JavaScript, чтобы иметь разные конструкторы
- 24. Как определить частные конструкторы в javascript?
- 25. Как вызвать конструкторы предков последовательно в JavaScript?
- 26. Конструкторы и как работает вызов в Javascript
- 27. Почему нам нужно определить конструкторы в JavaScript
- 28. Рекурсивно называют «родительские» конструкторы в Javascript?
- 29. Конструкторы и цепочка методов в JavaScript
- 30. Вызов функции в объектах с Javascript
[Douglas Крокфорд продвинутая JavaScript Video] (http://www.youtube.com/watch?v=DwYPG6vreJg) –
http://msdn.microsoft.com/en-us/library/202863ha%28VS .85% 29.aspx –