JavaScript에서 클래스를 정의하는 데 사용할 수있는 기술은 무엇이며 그 장단점은 무엇입니까?
나는 지금 작업하고있는 것과 같은 대규모 프로젝트에서 OOP를 사용하는 것을 선호합니다. 자바 스크립트로 여러 클래스를 만들어야하는데, 내가 착각하지 않는다면 적어도 몇 가지 방법이 있습니다. 구문은 무엇이며 왜 그런 식으로 수행됩니까?
적어도 처음에는 타사 라이브러리 사용을 피하고 싶습니다.
다른 답변을 찾고자 JavaScript의 객체 지향 프로그래밍에 대해 논의하는 JavaScript 를 사용한 객체 지향 프로그래밍, 파트 I : 상속-Doc JavaScript 기사를 찾았습니다 . 상속을 수행하는 더 좋은 방법이 있습니까?
다음은 외부 라이브러리를 사용하지 않고 수행하는 방법입니다.
// Define a class like this
function Person(name, gender){
// Add object properties like this
this.name = name;
this.gender = gender;
}
// Add methods like this. All Person objects will be able to invoke this
Person.prototype.speak = function(){
alert("Howdy, my name is" + this.name);
};
// Instantiate new objects with 'new'
var person = new Person("Bob", "M");
// Invoke methods like this
person.speak(); // alerts "Howdy, my name is Bob"
이제 실제 답은 그것보다 훨씬 더 복잡합니다. 예를 들어 JavaScript에는 클래스와 같은 것이 없습니다. JavaScript는 prototype
기반 상속 체계를 사용합니다 .
또한 JavaScript에서 클래스와 같은 기능을 근사화하는 고유 한 스타일을 가진 인기있는 JavaScript 라이브러리가 많이 있습니다. 최소한 Prototype 및 jQuery 를 확인하고 싶을 것 입니다.
이들 중 어떤 것이 "최고"인지 결정하는 것은 Stack Overflow에서 성스러운 전쟁을 시작하는 좋은 방법입니다. 더 큰 자바 스크립트가 많은 프로젝트를 시작한다면, 인기있는 라이브러리를 배우고 그 방식대로하는 것이 분명 가치가 있습니다. 나는 Prototype 사람이지만 Stack Overflow는 jQuery에 의지하는 것 같습니다.
외부 라이브러리에 대한 종속성없이 "한 가지 방법"만있는 한 내가 작성한 방식은 거의 동일합니다.
JavaScript에서 클래스를 정의하는 가장 좋은 방법은 클래스를 정의하지 않는 것입니다.
진지하게.
객체 지향에는 여러 가지 유형이 있으며 그중 일부는 다음과 같습니다.
- 클래스 기반 OO (Smalltalk에서 처음 도입)
- 프로토 타입 기반 OO (Self가 처음 도입)
- 멀티 메소드 기반 OO (처음으로 CommonLoops에서 소개 한 것 같습니다)
- 술어 기반 OO (모름)
그리고 아마도 내가 모르는 다른 것들.
JavaScript는 프로토 타입 기반 OO를 구현합니다. 프로토 타입 기반 OO에서 새로운 객체는 (클래스 템플릿에서 인스턴스화되는 대신) 다른 객체를 복사하여 생성되며 메서드는 클래스가 아닌 객체에 직접 존재합니다. 상속은 위임을 통해 수행됩니다. 객체에 메서드 나 속성이 없으면 프로토 타입 (즉, 복제 된 객체), 프로토 타입의 프로토 타입 등에서 조회됩니다.
즉, 수업이 없습니다.
JavaScript는 실제로 그 모델을 멋지게 조정했습니다 : 생성자. 기존 개체를 복사하여 개체를 만들 수있을뿐만 아니라 "공기에서"구성 할 수도 있습니다. new
키워드를 사용 하여 함수를 호출하면 해당 함수가 생성자가되고 this
키워드는 현재 객체를 가리 키지 않고 새로 생성 된 "빈"객체를 가리 킵니다. 따라서 원하는 방식으로 개체를 구성 할 수 있습니다. 이러한 방식으로 JavaScript 생성자는 기존 클래스 기반 OO에서 클래스의 역할 중 하나를 수행 할 수 있습니다. 새 객체에 대한 템플릿 또는 청사진 역할을합니다.
이제 JavaScript는 매우 강력한 언어이므로 원하는 경우 JavaScript 내에서 클래스 기반 OO 시스템을 구현하는 것이 매우 쉽습니다 . 그러나 Java가 수행하는 방식이 아니라 실제로 필요한 경우에만이 작업을 수행해야합니다.
ES2015 수업
ES2015 사양에서는 프로토 타입 시스템보다 당연한 클래스 구문을 사용할 수 있습니다.
class Person {
constructor(name) {
this.name = name;
}
toString() {
return `My name is ${ this.name }.`;
}
}
class Employee extends Person {
constructor(name, hours) {
super(name);
this.hours = hours;
}
toString() {
return `${ super.toString() } I work ${ this.hours } hours.`;
}
}
혜택
주요 이점은 정적 분석 도구가이 구문을 대상으로하는 것이 더 쉽다는 점입니다. 클래스 기반 언어에서 온 다른 사람들이 언어를 다중 언어로 사용하는 것이 더 쉽습니다.
주의 사항
현재 한계에주의하십시오. 개인 속성을 얻으려면 Symbols 또는 WeakMaps를 사용해야 합니다. 향후 릴리스에서는 이러한 누락 된 기능을 포함하도록 클래스가 확장 될 가능성이 높습니다.
지원하다
현재 브라우저 지원 은 그다지 좋지 않지만 (IE를 제외한 거의 모든 사람이 지원함) Babel 과 같은 트랜스 파일러에서 이러한 기능을 사용할 수 있습니다 .
자원
나는 Daniel X. Moore의 {SUPER: SYSTEM}
. 이것은 실제 인스턴스 변수, 특성 기반 상속, 클래스 계층 구조 및 구성 옵션과 같은 이점을 제공하는 분야입니다. 아래 예제는 가장 큰 장점이라고 생각하는 실제 인스턴스 변수의 사용을 보여줍니다. 인스턴스 변수가 필요하지 않고 공용 또는 전용 변수 만 만족한다면 더 간단한 시스템이있을 것입니다.
function Person(I) {
I = I || {};
Object.reverseMerge(I, {
name: "McLovin",
age: 25,
homeState: "Hawaii"
});
return {
introduce: function() {
return "Hi I'm " + I.name + " and I'm " + I.age;
}
};
}
var fogel = Person({
age: "old enough"
});
fogel.introduce(); // "Hi I'm McLovin and I'm old enough"
와우, 그 자체로는 그다지 유용하지 않지만 하위 클래스 추가를 살펴보십시오.
function Ninja(I) {
I = I || {};
Object.reverseMerge(I, {
belt: "black"
});
// Ninja is a subclass of person
return Object.extend(Person(I), {
greetChallenger: function() {
return "In all my " + I.age + " years as a ninja, I've never met a challenger as worthy as you...";
}
});
}
var resig = Ninja({name: "John Resig"});
resig.introduce(); // "Hi I'm John Resig and I'm 25"
또 다른 장점은 모듈 및 특성 기반 상속을 가질 수 있다는 것입니다.
// The Bindable module
function Bindable() {
var eventCallbacks = {};
return {
bind: function(event, callback) {
eventCallbacks[event] = eventCallbacks[event] || [];
eventCallbacks[event].push(callback);
},
trigger: function(event) {
var callbacks = eventCallbacks[event];
if(callbacks && callbacks.length) {
var self = this;
callbacks.forEach(function(callback) {
callback(self);
});
}
},
};
}
사람 클래스를 갖는 예는 바인딩 가능한 모듈을 포함합니다.
function Person(I) {
I = I || {};
Object.reverseMerge(I, {
name: "McLovin",
age: 25,
homeState: "Hawaii"
});
var self = {
introduce: function() {
return "Hi I'm " + I.name + " and I'm " + I.age;
}
};
// Including the Bindable module
Object.extend(self, Bindable());
return self;
}
var person = Person();
person.bind("eat", function() {
alert(person.introduce() + " and I'm eating!");
});
person.trigger("eat"); // Blasts the alert!
공개 : 저는 Daniel X. Moore이고 이것은 제 {SUPER: SYSTEM}
. JavaScript에서 클래스를 정의하는 가장 좋은 방법입니다.
var Animal = function(options) {
var name = options.name;
var animal = {};
animal.getName = function() {
return name;
};
var somePrivateMethod = function() {
};
return animal;
};
// usage
var cat = Animal({name: 'tiger'});
다음은 지금까지 사용한 자바 스크립트에서 객체를 만드는 방법입니다.
예 1 :
obj = new Object();
obj.name = 'test';
obj.sayHello = function() {
console.log('Hello '+ this.name);
}
예 2 :
obj = {};
obj.name = 'test';
obj.sayHello = function() {
console.log('Hello '+ this.name);
}
obj.sayHello();
예 3 :
var obj = function(nameParam) {
this.name = nameParam;
}
obj.prototype.sayHello = function() {
console.log('Hello '+ this.name);
}
예제 4 : Object.create ()의 실제 이점. [이 링크]를 참조하십시오
var Obj = {
init: function(nameParam) {
this.name = nameParam;
},
sayHello: function() {
console.log('Hello '+ this.name);
}
};
var usrObj = Object.create(Obj); // <== one level of inheritance
usrObj.init('Bob');
usrObj.sayHello();
예 5 (커스텀 Crockford의 Object.create) :
Object.build = function(o) {
var initArgs = Array.prototype.slice.call(arguments,1)
function F() {
if((typeof o.init === 'function') && initArgs.length) {
o.init.apply(this,initArgs)
}
}
F.prototype = o
return new F()
}
MY_GLOBAL = {i: 1, nextId: function(){return this.i++}} // For example
var userB = {
init: function(nameParam) {
this.id = MY_GLOBAL.nextId();
this.name = nameParam;
},
sayHello: function() {
console.log('Hello '+ this.name);
}
};
var bob = Object.build(userB, 'Bob'); // Different from your code
bob.sayHello();
ES6 / ES2015로 답변을 업데이트하려면
클래스는 다음과 같이 정의됩니다.
class Person {
constructor(strName, numAge) {
this.name = strName;
this.age = numAge;
}
toString() {
return '((Class::Person) named ' + this.name + ' & of age ' + this.age + ')';
}
}
let objPerson = new Person("Bob",33);
console.log(objPerson.toString());
Douglas Crockford의 Prototypal Inheritance in JavaScript 와 Classical Inheritance in JavaScript를 읽어야한다고 생각합니다 .
그의 페이지의 예 :
Function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
};
효과? 보다 우아한 방식으로 메소드를 추가 할 수 있습니다.
function Parenizor(value) {
this.setValue(value);
}
Parenizor.method('setValue', function (value) {
this.value = value;
return this;
});
나는 또한 그의 비디오를 추천한다 : Advanced JavaScript .
그의 페이지에서 더 많은 비디오를 찾을 수 있습니다 : http://javascript.crockford.com/ John Reisig 책에서 Douglas Crockfor의 웹 사이트에서 많은 예제를 찾을 수 있습니다.
나는 YUI / Crockford 공장 계획을 인정하지 않을 것이며, 모든 것을 독립적이고 확장 가능한 상태로 유지하기를 원하기 때문에 이것이 나의 변형입니다.
function Person(params)
{
this.name = params.name || defaultnamevalue;
this.role = params.role || defaultrolevalue;
if(typeof(this.speak)=='undefined') //guarantees one time prototyping
{
Person.prototype.speak = function() {/* do whatever */};
}
}
var Robert = new Person({name:'Bob'});
이상적으로 typeof 테스트는 프로토 타입 된 첫 번째 방법과 같은 것입니다.
단순하게하려는 경우 "new"키워드를 완전히 피하고 팩토리 메소드 만 사용할 수 있습니다. 나는 JSON을 사용하여 객체를 만드는 것을 좋아하기 때문에 때때로 이것을 선호합니다.
function getSomeObj(var1, var2){
var obj = {
instancevar1: var1,
instancevar2: var2,
someMethod: function(param)
{
//stuff;
}
};
return obj;
}
var myobj = getSomeObj("var1", "var2");
myobj.someMethod("bla");
그래도 큰 물체에 대한 성능 저하가 무엇인지 잘 모르겠습니다.
var Student = (function () {
function Student(firstname, lastname) {
this.firstname = firstname;
this.lastname = lastname;
this.fullname = firstname + " " + lastname;
}
Student.prototype.sayMyName = function () {
return this.fullname;
};
return Student;
}());
var user = new Student("Jane", "User");
var user_fullname = user.sayMyName();
이것이 TypeScript가 생성자와 함께 클래스를 JavaScript로 컴파일하는 방식입니다.
간단한 방법은 다음과 같습니다.
function Foo(a) {
var that=this;
function privateMethod() { .. }
// public methods
that.add = function(b) {
return a + b;
};
that.avg = function(b) {
return that.add(b) / 2; // calling another public method
};
}
var x = new Foo(10);
alert(x.add(2)); // 12
alert(x.avg(20)); // 15
그 이유는 대한 that
이가있다 this
당신이 이벤트 핸들러 등의 방법을 제공하는 경우가 인스턴스화하는 동안 값을 저장하고 나중에 사용할 수 있도록, 다른 것을 결합 할 수 있습니다.
편집 : 확실히 최선의 방법이 아니라 단순한 방법입니다. 나도 좋은 답변을 기다리고 있어요!
접기 패턴을 사용하여 유형을 작성하려고 할 수 있습니다.
// Here is the constructor section.
var myType = function () {
var N = {}, // Enclosed (private) members are here.
X = this; // Exposed (public) members are here.
(function ENCLOSED_FIELDS() {
N.toggle = false;
N.text = '';
}());
(function EXPOSED_FIELDS() {
X.count = 0;
X.numbers = [1, 2, 3];
}());
// The properties below have access to the enclosed fields.
// Careful with functions exposed within the closure of the
// constructor, each new instance will have it's own copy.
(function EXPOSED_PROPERTIES_WITHIN_CONSTRUCTOR() {
Object.defineProperty(X, 'toggle', {
get: function () {
var before = N.toggle;
N.toggle = !N.toggle;
return before;
}
});
Object.defineProperty(X, 'text', {
get: function () {
return N.text;
},
set: function (value) {
N.text = value;
}
});
}());
};
// Here is the prototype section.
(function PROTOTYPE() {
var P = myType.prototype;
(function EXPOSED_PROPERTIES_WITHIN_PROTOTYPE() {
Object.defineProperty(P, 'numberLength', {
get: function () {
return this.numbers.length;
}
});
}());
(function EXPOSED_METHODS() {
P.incrementNumbersByCount = function () {
var i;
for (i = 0; i < this.numbers.length; i++) {
this.numbers[i] += this.count;
}
};
P.tweak = function () {
if (this.toggle) {
this.count++;
}
this.text = 'tweaked';
};
}());
}());
이 코드는 myType 이라는 유형을 제공합니다 . toggle 및 text 라는 내부 비공개 필드가 있습니다 . 또한 다음과 같은 노출 된 멤버가 있습니다. 필드 개수 및 숫자 ; 속성 토글 , 텍스트 및 numberLength ; incrementNumbersByCount 및 tweak 메소드 .
접기 패턴은 여기에 자세히 설명되어 있습니다 : 자바 스크립트 접기 패턴
@liammclennan의 답변에 대한 코드 골프 .
var Animal = function (args) {
return {
name: args.name,
getName: function () {
return this.name; // member access
},
callGetName: function () {
return this.getName(); // method call
}
};
};
var cat = Animal({ name: 'tiger' });
console.log(cat.callGetName());
MooTools (My Object Oriented Tools)는 클래스 개념에 중점을 둡니다 . 상속을 통해 확장하고 구현할 수도 있습니다.
마스터하면 엄청나게 재사용이 가능하고 강력한 자바 스크립트가됩니다.
상속이있는 객체 기반 클래스
var baseObject =
{
// Replication / Constructor function
new : function(){
return Object.create(this);
},
aProperty : null,
aMethod : function(param){
alert("Heres your " + param + "!");
},
}
newObject = baseObject.new();
newObject.aProperty = "Hello";
anotherObject = Object.create(baseObject);
anotherObject.aProperty = "There";
console.log(newObject.aProperty) // "Hello"
console.log(anotherObject.aProperty) // "There"
console.log(baseObject.aProperty) // null
간단하고 달콤하며 끝납니다.
베이스
function Base(kind) {
this.kind = kind;
}
클래스
// Shared var
var _greeting;
(function _init() {
Class.prototype = new Base();
Class.prototype.constructor = Class;
Class.prototype.log = function() { _log.apply(this, arguments); }
_greeting = "Good afternoon!";
})();
function Class(name, kind) {
Base.call(this, kind);
this.name = name;
}
// Shared function
function _log() {
console.log(_greeting + " Me name is " + this.name + " and I'm a " + this.kind);
}
동작
var c = new Class("Joe", "Object");
c.log(); // "Good afternoon! Me name is Joe and I'm a Object"
Triptych의 예를 기반으로하면 더 간단 할 수 있습니다.
// Define a class and instantiate it
var ThePerson = new function Person(name, gender) {
// Add class data members
this.name = name;
this.gender = gender;
// Add class methods
this.hello = function () { alert('Hello, this is ' + this.name); }
}("Bob", "M"); // this instantiates the 'new' object
// Use the object
ThePerson.hello(); // alerts "Hello, this is Bob"
이것은 단일 객체 인스턴스 만 생성하지만, 클래스의 변수 및 메소드에 대한 이름을 캡슐화하려는 경우 여전히 유용합니다. 일반적으로 생성자에 대한 "Bob, M"인수는 없습니다. 예를 들어 메서드가 데이터베이스 나 네트워크와 같은 자체 데이터를 사용하여 시스템에 대한 호출이되는 경우입니다.
나는 JS가 왜 이것을 사용하지 않는지 알기에는 여전히 너무 새롭습니다 prototype
.
JavaScript는 객체 지향적 이지만 Java, C # 또는 C ++와 같은 다른 OOP 언어와 근본적으로 다릅니다 . 그렇게 이해하려고하지 마십시오. 그 오래된 지식을 버리고 새로 시작하십시오. JavaScript는 다른 생각이 필요합니다.
나는 주제에 대한 좋은 매뉴얼이나 무언가를 얻는 것이 좋습니다. 필자 는 프레임 워크를 읽거나 읽은 후 프레임 워크를 사용 해본 적이 없지만 ExtJS Tutorials 가 저에게 가장 적합 하다는 것을 알게되었습니다 . 그러나 그것은 JavaScript 세계에서 무엇이 무엇인지에 대한 좋은 설명을 제공합니다. 죄송합니다. 콘텐츠가 삭제 된 것 같습니다. 대신 archive.org 사본에 대한 링크가 있습니다. 오늘 작동합니다. :피
//new way using this and new
function Persons(name) {
this.name = name;
this.greeting = function() {
alert('Hi! I\'m ' + this.name + '.');
};
}
var gee=new Persons("gee");
gee.greeting();
var gray=new Persons("gray");
gray.greeting();
//old way
function createPerson(name){
var obj={};
obj.name=name;
obj.greeting = function(){
console.log("hello I am"+obj.name);
};
return obj;
}
var gita=createPerson('Gita');
gita.greeting();
'code' 카테고리의 다른 글
이미지를 깔끔하게 빌드하기 위해 Docker를 강제하는 방법 (0) | 2020.10.02 |
---|---|
변수를 사용하여 객체 속성에 동적으로 액세스 (0) | 2020.10.02 |
C #에서 string.Empty 또는 String.Empty 또는 ""를 사용하여 문자열을 초기화해야합니까? (0) | 2020.09.30 |
Android 텍스트 뷰 주위에 테두리를 어떻게 두나요? (0) | 2020.09.30 |
레이아웃의 Android 드로잉 구분선 / 분할 선? (0) | 2020.09.30 |