[javascript] JavaScript로 객체를 만드는 데 가장 좋은 방법은 무엇입니까? 객체 속성 앞에 ‘var’이 필요합니까?

지금까지 JavaScript로 객체를 만드는 세 가지 방법을 보았습니다. 객체를 만드는 데 가장 적합한 방법은 무엇입니까?

또한이 모든 예에서 키워드 var가 속성 앞에 사용되지 않는 것을 알았습니다. 왜 그렇 습니까? var속성이 변수라고 언급 했으므로 속성 이름 앞에 선언 할 필요가 없습니까?

두 번째 및 세 번째 방법에서는 개체 이름이 대문자 인 반면 첫 번째 방법에서는 개체 이름이 소문자입니다. 객체 이름에 어떤 경우를 사용해야합니까?

첫 번째 방법 :

function person(fname, lname, age, eyecolor){
  this.firstname = fname;
  this.lastname = lname;
  this.age = age;
  this.eyecolor = eyecolor;
}

myFather = new person("John", "Doe", 50, "blue");
document.write(myFather.firstname + " is " + myFather.age + " years old.");

두 번째 방법 :

var Robot = {
  metal: "Titanium",
  killAllHumans: function(){
    alert("Exterminate!");
  }
};

Robot.killAllHumans();

세 번째 방법 — 배열 구문을 사용하는 JavaScript 객체 :

var NewObject = {};

NewObject['property1'] = value;
NewObject['property2'] = value;
NewObject['method'] = function(){ /* function code here */ }



답변

최선의 방법 은 없습니다 . 사용 사례에 따라 다릅니다.

  • 유사한 객체를 여러 개 만들려면 방법 1을 사용하십시오 . 귀하의 예에서 Person(대문자로 이름을 시작해야 함)을 생성자 함수 라고합니다 . 이것은 다른 OO 언어의 클래스 와 유사합니다 .
  • 단일 객체 와 같은 종류의 객체 가 하나만 필요한 경우 방법 2를 사용하십시오 . 이 객체가 다른 객체에서 상속되도록하려면 생성자 함수를 사용해야합니다.
  • 객체의 다른 속성에 따라 객체의 속성을 초기화하거나 동적 속성 이름이있는 경우 방법 3을 사용하십시오 .

업데이트 : 세 번째 방법으로 요청한 예.

종속 속성 :

다음은 작동하지 this않습니다 하지 를 참조하십시오 book. 객체 리터럴에서 다른 속성 값으로 속성을 초기화 할 수있는 방법이 없습니다.

var book = {
    price: somePrice * discount,
    pages: 500,
    pricePerPage: this.price / this.pages
};

대신, 당신은 할 수 있습니다 :

var book = {
    price: somePrice * discount,
    pages: 500
};
book.pricePerPage = book.price / book.pages;
// or book['pricePerPage'] = book.price / book.pages;

동적 속성 이름 :

속성 이름이 변수에 저장되거나 식을 통해 생성 된 경우 대괄호 표기법을 사용해야합니다.

var name = 'propertyName';

// the property will be `name`, not `propertyName`
var obj = {
    name: 42
};

// same here
obj.name = 42;

// this works, it will set `propertyName`
obj[name] = 42;


답변

함수를 정의하는 다양한 방법이 있습니다. 그것은 전적으로 귀하의 요구 사항을 기반으로합니다. 아래는 몇 가지 스타일입니다 :-

  1. 객체 생성자
  2. 리터럴 생성자
  3. 기능 기반
  4. 프로토 이프 기반
  5. 기능 및 프로토 타입 기반
  6. 싱글 톤 기반

예 :

  1. 객체 생성자
var person = new Object();

person.name = "Anand",
person.getName = function(){
  return this.name ;
};
  1. 리터럴 생성자
var person = {
  name : "Anand",
  getName : function (){
   return this.name
  }
} 
  1. 함수 생성자
function Person(name){
  this.name = name
  this.getName = function(){
    return this.name
  }
} 
  1. 원기
function Person(){};

Person.prototype.name = "Anand";
  1. 기능 / 시제품 조합
function Person(name){
  this.name = name;
}
Person.prototype.getName = function(){
  return this.name
} 
  1. 하나씩 일어나는 것
var person = new function(){
  this.name = "Anand"
} 

혼란이 있다면 콘솔에서 시도해 볼 수 있습니다.


답변

개체를 만드는 “최상의 방법”은 없습니다. 각 방법에는 사용 사례에 따라 이점이 있습니다.

생성자 패턴 ( new 이를 호출하기 위해 연산자 )은 프로토 타입 상속을 사용할 가능성을 제공하지만 다른 방법은 그렇지 않습니다. 따라서 프로토 타입 상속을 원한다면 생성자 함수를 사용하는 것이 좋습니다.

그러나 프로토 타입 상속을 원한다면을 사용할 수도 있습니다 Object.create.

객체 리터럴 (ex :)을 생성하면 var obj = {foo: "bar"};생성시 설정하려는 모든 속성이있는 경우 효과적입니다.

나중에 속성을 설정 하려면 속성 이름을 아는 경우 NewObject.property1일반적으로 구문이 선호됩니다 NewObject['property1']. 그러나 후자는 실제로 사전에 부동산 이름이없는 경우에 유용합니다 (예 :NewObject[someStringVar] .

도움이 되었기를 바랍니다!


답변

나는 그것이 당신이 원하는 것에 달려 있다고 생각합니다. 간단한 객체의 경우 두 번째 방법을 사용할 수 있습니다. 물체가 커지고 비슷한 물체를 사용할 계획이라면 첫 번째 방법이 더 좋을 것 같습니다. 이렇게하면 프로토 타입을 사용하여 확장 할 수도 있습니다.

예:

function Circle(radius) {
    this.radius = radius;
}
Circle.prototype.getCircumference = function() {
    return Math.PI * 2 * this.radius;
};
Circle.prototype.getArea = function() {
    return Math.PI * this.radius * this.radius;
}

세 번째 방법을 좋아하지는 않지만 예를 들어 속성을 동적으로 편집하는 데 실제로 유용합니다 var foo='bar'; var bar = someObject[foo];.


답변

JavaScript로 객체를 작성하는 방법에는 여러 가지가 있습니다. 생성자 함수를 사용하여 객체 또는 객체 리터럴 표기법을 만드는 것은 JavaScript에서 많은 것을 사용하는 것입니다. 또한 Object의 인스턴스를 생성 한 다음 속성과 메소드를 추가하면 JavaScript로 객체를 생성하는 세 가지 일반적인 방법이 있습니다.

생성자 함수

Date (), Number (), Boolean () 등과 같이 우리 모두가 때때로 사용할 수있는 내장 생성자 함수가 있습니다. 모든 생성자 함수는 대문자로 시작합니다. 이처럼 :

function Box (Width, Height, fill) {
  this.width = Width;  // The width of the box 
  this.height = Height;  // The height of the box 
  this.fill = true;  // Is it filled or not?
}  

new ()를 사용하여 생성자의 새 인스턴스를 생성하고 아래와 같은 것을 생성하고 채워진 매개 변수로 생성자 함수를 호출하면됩니다.

var newBox = new Box(8, 12, true);  

객체 리터럴

객체 리터럴을 사용하는 것은 JavaScript로 객체를 생성하는 경우에 매우 많이 사용됩니다.이 간단한 객체를 만드는 예는 객체 속성이 정의되어있는 한 무엇이든 객체 속성에 할당 할 수 있습니다.

var person = {
    name: "Alireza",
    surname: "Dezfoolian"
    nose: 1,
    feet: 2,
    hands: 2,
    cash: null
};  

프로토 타이핑

Object를 생성 한 후 더 많은 멤버를 프로토 타입으로 만들 수 있습니다 (예 : Box에 색상 추가).

Box.prototype.colour = 'red';


답변

여기에 많은 사람들이 객체 생성을위한 최선의 방법은 없다고 말하지만 2019 년 현재 JavaScript로 객체를 생성하는 방법이 너무 많은 이유에 대한 근거가 있으며, 이는 다른 반복에서 JavaScript의 진행과 관련이 있습니다 1997 년에 설립 된 EcmaScript 릴리스.

ECMAScript 5 이전에는 생성자 함수 또는 리터럴 표기법 (new Object ()에 대한 더 나은 대안)이라는 두 가지 방법으로 객체를 만들 수있었습니다. 생성자 함수 표기법을 사용하면 여러 키워드로 인스턴스화 할 수있는 객체를 만들고 (새 키워드로) 리터럴 표기법은 싱글 톤과 같은 단일 객체를 제공합니다.

// constructor function
function Person() {};

// literal notation
var Person = {};

사용하는 방법에 관계없이 JavaScript 객체는 단순히 키 값 쌍의 속성입니다.

// Method 1: dot notation
obj.firstName = 'Bob';

// Method 2: bracket notation. With bracket notation, you can use invalid characters for a javascript identifier.
obj['lastName'] = 'Smith';

// Method 3: Object.defineProperty
Object.defineProperty(obj, 'firstName', {
    value: 'Bob',
    writable: true,
    configurable: true,
    enumerable: false
})

// Method 4: Object.defineProperties
Object.defineProperties(obj, {
  firstName: {
    value: 'Bob',
    writable: true
  },
  lastName: {
    value: 'Smith',
    writable: false
  }
});

JavaScript의 초기 버전에서 클래스 기반 상속을 모방하는 유일한 방법은 생성자 함수를 사용하는 것입니다. 생성자 함수는 ‘new’키워드로 호출되는 특수 함수입니다. 관례에 따라 함수 식별자는 대문자로 표시되지만 필수는 아닙니다. 생성자 내부에서 생성자 함수가 내재적으로 생성하는 객체에 속성을 추가하기 위해 ‘this’키워드를 참조합니다. return 키워드를 명시 적으로 사용하고 다른 것을 반환하지 않는 한 생성자 함수는 채워진 속성이있는 새 객체를 암시 적으로 호출 함수에 암시 적으로 반환합니다.

function Person(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;

    this.sayName = function(){
        return "My name is " + this.firstName + " " + this.lastName;
    }
}

var bob = new Person("Bob", "Smith");
bob instanceOf Person // true

sayName 메소드에 문제가 있습니다. 일반적으로 객체 지향 클래스 기반 프로그래밍 언어에서는 클래스를 팩토리로 사용하여 객체를 만듭니다. 각 객체에는 자체 인스턴스 변수가 있지만 클래스 청사진에 정의 된 메소드에 대한 포인터가 있습니다. 불행히도, JavaScript 생성자 함수를 사용할 때, 그것이 호출 될 때마다 새로 생성 된 객체에 새로운 sayName 속성을 정의합니다. 따라서 각 객체에는 고유 한 sayName 속성이 있습니다. 이것은 더 많은 메모리 리소스를 소비합니다.

증가 된 메모리 자원 외에도 생성자 함수 내에 메소드를 정의하면 상속 가능성이 제거됩니다. 이 메소드는 새로 작성된 오브젝트의 특성으로 정의되며 다른 오브젝트는 정의되지 않으므로 상속이 작동하지 않습니다. 따라서 JavaScript는 프로토 타입 체인을 상속 형태로 제공하여 JavaScript를 프로토 타입 언어로 만듭니다.

부모가 있고 부모가 자식의 많은 속성을 공유하는 경우 자식은 해당 속성을 상속해야합니다. ES5 이전에는 다음과 같이 수행되었습니다.

function Parent(eyeColor, hairColor) {
    this.eyeColor = eyeColor;
    this.hairColor = hairColor;
}

Parent.prototype.getEyeColor = function() {
  console.log('has ' + this.eyeColor);
}

Parent.prototype.getHairColor = function() {
  console.log('has ' + this.hairColor);
}

function Child(firstName, lastName) {
  Parent.call(this, arguments[2], arguments[3]);
  this.firstName = firstName;
  this.lastName = lastName;
}

Child.prototype = Parent.prototype;

var child = new Child('Bob', 'Smith', 'blue', 'blonde');
child.getEyeColor(); // has blue eyes
child.getHairColor(); // has blonde hair

위의 프로토 타입 체인을 활용 한 방식에는 단점이 있습니다. 프로토 타입은 라이브 링크이므로 프로토 타입 체인에서 한 객체의 속성을 변경하면 다른 객체의 동일한 속성도 변경됩니다. 자식의 상속 된 메소드를 변경해도 부모의 메소드는 변경되지 않아야합니다. Object.create는 폴리 필을 사용하여이 문제를 해결했습니다. 따라서 Object.create를 사용하면 프로토 타입 체인에서 부모의 동일한 속성에 영향을주지 않고 프로토 타입 체인에서 자식 속성을 안전하게 수정할 수 있습니다.

ECMAScript 5는 객체 생성을위한 생성자 함수에서 위에서 언급 한 버그를 해결하기 위해 Object.create를 도입했습니다. Object.create () 메소드는 기존 오브젝트를 새로 작성된 오브젝트의 프로토 타입으로 사용하여 새 오브젝트를 작성합니다. 새 객체가 생성되었으므로 더 이상 프로토 타입 체인에서 하위 속성을 수정하면 체인에서 해당 속성에 대한 부모의 참조가 수정되는 문제가 없습니다.

var bobSmith = {
    firstName: "Bob",
    lastName: "Smith",
    sayName: function(){
      return "My name is " + this.firstName + " " + this.lastName;
    }
}

var janeSmith = Object.create(bobSmith, {
    firstName : {  value: "Jane" }
})

console.log(bobSmith.sayName()); // My name is Bob Smith
console.log(janeSmith.sayName()); // My name is Jane Smith
janeSmith.__proto__ == bobSmith; // true
janeSmith instanceof bobSmith; // Uncaught TypeError: Right-hand side of 'instanceof' is not callable. Error occurs because bobSmith is not a constructor function.

ES6 이전에는 함수 생성자와 Object.create를 활용하는 일반적인 생성 패턴이 있습니다.

const View = function(element){
  this.element = element;
}

View.prototype = {
  getElement: function(){
    this.element
  }
}

const SubView = function(element){
  View.call(this, element);
}

SubView.prototype = Object.create(View.prototype);

이제 생성자 함수와 결합 된 Object.create는 JavaScript에서 객체 생성 및 상속에 널리 사용되었습니다. 그러나 ES6는 클래스 개념을 도입했는데, 이는 주로 JavaScript의 기존 프로토 타입 기반 상속에 비해 구문상의 설탕입니다. 클래스 구문은 JavaScript에 새로운 객체 지향 상속 모델을 도입하지 않습니다. 따라서 JavaScript는 프로토 타입 언어로 남아 있습니다.

ES6 클래스는 상속을 훨씬 쉽게 만듭니다. 더 이상 부모 클래스의 프로토 타입 함수를 수동으로 복사하고 자식 클래스의 생성자를 재설정 할 필요가 없습니다.

// create parent class
class Person {
  constructor (name) {
    this.name = name;
  }
}

// create child class and extend our parent class
class Boy extends Person {
  constructor (name, color) {
    // invoke our parent constructor function passing in any required parameters
    super(name);

    this.favoriteColor = color;
  }
}

const boy = new Boy('bob', 'blue')
boy.favoriteColor; // blue

자바 스크립트에서이 5 가지의 서로 다른 객체 생성 전략은 EcmaScript 표준의 발전과 일치했습니다.


답변

물론 가장 좋은 방법이 있습니다. 자바 스크립트의 객체에는 열거 가능하고 셀 수없는 속성이 있습니다.

var empty = {};
console.log(empty.toString);
// . function toString(){...}
console.log(empty.toString());
// . [object Object]

위의 예에서 빈 객체에는 실제로 속성이 있음을 알 수 있습니다.

먼저 가장 좋은 방법을 보자.

var new_object = Object.create(null)

new_object.name = 'Roland'
new_object.last_name = 'Doda'
//etc

console.log("toString" in new_object) //=> false

위의 예에서 로그는 false를 출력합니다.

이제 다른 객체 생성 방법이 왜 틀린지 봅시다.

//Object constructor
var object = new Object();

console.log("toString" in object); //=> true

//Literal constructor
var person = {
  name : "Anand",
  getName : function (){
   return this.name
  }
}

console.log("toString" in person); //=> true

//function Constructor
function Person(name){
  this.name = name
  this.getName = function(){
    return this.name
  }
}

var person = new Person ('landi')

console.log("toString" in person); //=> true

//Prototype
function Person(){};

Person.prototype.name = "Anand";

console.log("toString" in person); //=> true

//Function/Prototype combination
function Person2(name){
  this.name = name;
}

Person2.prototype.getName = function(){
  return this.name
}

var person2 = new Person2('Roland')

console.log("toString" in person2) //=> true

위에서 볼 수 있듯이 모든 예제는 true를 기록합니다. 즉 for in, 객체에 속성이 있는지 확인하기 위해 루프가있는 경우 잘못된 결과가 발생할 수 있습니다.

가장 쉬운 방법은 쉽지 않습니다. 객체의 모든 속성을 한 줄씩 정의해야합니다. 다른 방법은 더 쉽고 객체를 만드는 데 필요한 코드가 적지 만 경우에 따라 알아 두어야합니다. 나는 항상 “다른 방법”을 사용하고 가장 좋은 방법을 사용하지 않으면 위의 경고에 대한 한 가지 해결책은 다음과 같습니다.

 for (var property in new_object) {
  if (new_object.hasOwnProperty(property)) {
    // ... this is an own property
  }
 }