[javascript] JavaScript로 클래스를 정의하는 데 사용할 수있는 기술은 무엇이며 그 상충 관계는 무엇입니까?

현재 작업중인 것과 같은 대규모 프로젝트에서 OOP를 사용하는 것을 선호합니다. JavaScript로 여러 클래스를 만들어야하지만 실수하지 않은 경우 적어도 두 가지 방법으로 수행 할 수 있습니다. 구문은 무엇이며 왜 그런 식으로 수행됩니까?

적어도 처음에는 타사 라이브러리를 사용하고 싶지 않습니다.
다른 답변을 찾으려면 JavaScript로 객체 지향 프로그래밍에 대해 설명하는 JavaScript로 객체 지향 프로그래밍 , 1 부 : 상속-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 라이브러리가 많이 있습니다. 적어도 프로토 타입jQuery 를 확인하고 싶을 것이다 .

이 중 “최고”를 결정하는 것은 Stack Overflow에서 거룩한 전쟁을 시작하는 좋은 방법입니다. 더 큰 JavaScript가 많은 프로젝트를 시작하는 경우 인기있는 라이브러리를 배우고 그 방식대로 수행하는 것이 좋습니다. 저는 프로토 타입 사람이지만 스택 오버플로는 jQuery에 의존하는 것 같습니다.

외부 라이브러리에 의존하지 않고 “한 가지 방법”만있는 한, 내가 쓴 방식은 거의 비슷합니다.


답변

JavaScript에서 클래스를 정의하는 가장 좋은 방법은 클래스를 정의하지 않는 것입니다.

진심으로.

여러 가지 방향의 객체 지향이 있으며 그중 일부는 다음과 같습니다.

  • 클래스 기반 OO (Smalltalk에서 처음 소개)
  • 프로토 타입 기반 OO (자체에서 처음 소개)
  • 멀티 메소드 기반 OO (CommonLoops가 처음 도입 한 것 같습니다.)
  • 술어 기반 OO (모름)

그리고 아마 내가 모르는 다른 사람들.

JavaScript는 프로토 타입 기반 OO를 구현합니다. 프로토 타입 기반 OO에서는 클래스 템플릿에서 인스턴스화되는 대신 다른 개체를 복사하여 새 개체를 만들고 메서드는 클래스 대신 개체에 직접 존재합니다. 상속은 위임을 통해 수행됩니다. 객체에 메서드 나 속성이없는 경우 프로토 타입 (즉, 복제 된 객체)과 프로토 타입의 프로토 타입 등을 찾습니다.

다시 말해, 수업이 없습니다.

자바 스크립트는 실제로 그 모델에 대한 훌륭한 조정이있다 : 생성자. 기존 객체를 복사하여 객체를 만들 수있을뿐만 아니라 “얇은 공기가없는”객체를 만들 수도 있습니다. 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 ‘s를 선호합니다 {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);
        });
      }
    },
  };
}

person 클래스를 갖는 예에는 바인딩 가능한 모듈이 있습니다.

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());


답변

JavaScript에서 Douglas Crockford의 Prototypal Inheritance와 JavaScript 에서 Classical Inheritance를 읽어야한다고 생각합니다 .

그의 페이지에서 예 :

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의 웹 사이트에서 많은 예제를 찾을 수 있습니다.