source

"new" 대신 "Object.create" 사용

nicesource 2023. 1. 19. 07:04
반응형

"new" 대신 "Object.create" 사용

1.는 Javascript 1.9.3/ECMAScript 5를 했습니다.Object.create더글라스 크록포드가 오랫동안 지지해 온 것이다.치환 방법new에는 「」가 붙어 있습니다.Object.create

var UserA = function(nameParam) {
    this.id = MY_GLOBAL.nextId();
    this.name = nameParam;
}
UserA.prototype.sayHello = function() {
    console.log('Hello '+ this.name);
}
var bob = new UserA('bob');
bob.sayHello();

(가定))MY_GLOBAL.nextId존재합니다).

내가 생각해 낼 수 있는 최선의 방법은:

var userB = {
    init: function(nameParam) {
        this.id = MY_GLOBAL.nextId();
        this.name = nameParam;
    },
    sayHello: function() {
        console.log('Hello '+ this.name);
    }
};
var bob = Object.create(userB);
bob.init('Bob');
bob.sayHello();

장점이 없는 것 같아서 이해가 안 되는 것 같아요.내가 너무 신 고전주의적으로 구는 것 같아.★★★의 Object.create용밥밥밥을을을을을을을을을?

상속 수준이 1개뿐일 경우 이 예에서는 의 실제 이점을 확인할 수 없을 수 있습니다.

이 방법을 사용하면 개체가 다른 개체에서 직접 상속할 수 있는 차등 상속을 쉽게 구현할 수 있습니다.

★★★★★★★★★★★★★★★★★★★★★★★에userB를 들어, 나는 너의 '나'나 '나'가 '나'라고는하지 않는다init.이 public이 존재합니다.기존 오브젝트인스턴스에서 이 메서드를 다시 호출하면id ★★★★★★★★★★★★★★★★★」name속성이 변경됩니다.

Object.create그럼 두 번째 인수를 사용하여 오브젝트 속성을 초기화할 수 있습니다.하다

var userB = {
  sayHello: function() {
    console.log('Hello '+ this.name);
  }
};

var bob = Object.create(userB, {
  'id' : {
    value: MY_GLOBAL.nextId(),
    enumerable:true // writable:false, configurable(deletable):false by default
  },
  'name': {
    value: 'Bob',
    enumerable: true
  }
});

두 로 속성을 할 수 .Object.create하여, 에서 되는 구문과 Object.defineProperties ★★★★★★★★★★★★★★★★★」Object.defineProperty★★★★★★★★★★★★★★★★★★.

속성)을 할 수 .enumerable,writable , 「」configurable매우 편리합니다.

사용해도 이 없어요.Object.create(...)에 걸쳐서new object.

이 방법을 지지하는 사람들은 일반적으로 "확장성" 또는 "JavaScript에 보다 자연스러운" 등의 다소 애매한 이점을 언급합니다.

아직 를 못 요.Object.create사용하는 것에 비해 이점이 있다new반대로, 이미 알려진 문제가 있습니다.Sam Elsamman은 중첩된 개체가 있을 때 발생하는 작업을 설명합니다.

var Animal = {
    traits: {},
}
var lion = Object.create(Animal);
lion.traits.legs = 4;
var bird = Object.create(Animal);
bird.traits.legs = 2;
alert(lion.traits.legs) // shows 2!!!

이유는 '먹다'가 '먹다'이기 때문입니다.Object.create(...)새로운 오브젝트를 작성하기 위해 데이터를 사용하는 관행을 지지합니다.여기서Animal은 시제품의 일부가 .lion ★★★★★★★★★★★★★★★★★」bird공유 시 문제가 발생합니다.새로운 프로토타입을 사용할 경우 다음과 같이 명확하게 상속됩니다.

function Animal() {
    this.traits = {};
}

function Lion() { }
Lion.prototype = new Animal();
function Bird() { }
Bird.prototype = new Animal();

var lion = new Lion();
lion.traits.legs = 4;
var bird = new Bird();
bird.traits.legs = 2;
alert(lion.traits.legs) // now shows 4

Object.create(...)를 사용하여 추가할 수 있습니다.

object.create는 IE8, Opera v11.5, Konq 4.3 등 여러 브라우저에서 아직 표준이 아닙니다.이러한 브라우저에는 Douglas Crockford 버전의 Object.create를 사용할 수 있지만 CMS 응답에 사용된 두 번째 'initialization object' 파라미터는 포함되지 않습니다.

크로스 브라우저 코드의 경우 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()
}

그러면 Crockford 프로토타입 상속이 유지되고 객체의 init 메서드가 있는지 확인한 다음 new man('John' 'Smith')과 같이 매개 변수를 사용하여 실행됩니다.그 후 코드는 다음과 같습니다.

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

따라서 bob은 sayHello 메서드를 상속하여 이제 자체 속성 id=1 및 name='Bob'을 가집니다.이러한 속성은 물론 쓰기 가능하고 열거할 수 있습니다.이 방법은 ECMA Object.create보다 훨씬 간단하게 초기화할 수 있습니다.특히 쓰기 가능, 열거 가능, 구성 가능한 속성이 염려되지 않는 경우에는 더욱 그렇습니다.

초기 방법 없이 초기화를 위해 다음과 같은 Crockford 모드를 사용할 수 있다.

Object.gen = function(o) {
   var makeArgs = arguments 
   function F() {
      var prop, i=1, arg, val
      for(prop in o) {
         if(!o.hasOwnProperty(prop)) continue
         val = o[prop]
         arg = makeArgs[i++]
         if(typeof arg === 'undefined') break
         this[prop] = arg
      }
   }
   F.prototype = o
   return new F()
}

userB 파라미터의 왼쪽에서 오른쪽 뒤에 Object.gen 파라미터를 사용하여 정의된 순서대로 사용자B 자신의 속성을 채웁니다.for(prop in o) 루프를 사용하기 때문에 ECMA 표준에서는 속성 정의 순서와 동일한 속성 열거 순서를 보장할 수 없습니다.단, (4)개의 메이저브라우저에서 테스트된 몇 가지 코드 예에서는 hasOwnProperty 필터가 사용되고 있는 경우 또는 사용되지 않는 경우라도 동일함을 알 수 있습니다.

MY_GLOBAL = {i: 1, nextId: function(){return this.i++}};  // For example

var userB = {
   name: null,
   id: null,
   sayHello: function() {
      console.log('Hello '+ this.name);
   }
}

var bob = Object.gen(userB, 'Bob', MY_GLOBAL.nextId());

오브젝트보다 조금 더 간단하다고 말할 수 있습니다.사용자 B에는 init 메서드가 필요 없기 때문에 빌드합니다.또한 userB는 특별히 컨스트럭터가 아니라 일반적인 싱글톤 오브젝트처럼 보입니다.따라서 이 방법을 사용하면 일반 일반 개체에서 구성 및 초기화할 수 있습니다.

TL;DR:

new Computer() 함수를 합니다.Computer(){}Object.create(Computer.prototype)할 거예요.

모든 장점은 이 점에 근거를 두고 있다.

호출: 호출과 같은new Computer()에 의해 되어 있기 에, 수 .Object.create.

해서 만들 수 있어요.init return " " " "this 해서 체인을 이렇게 체인을 하다, 하다, 하다, 하다

var userB = {
    init: function(nameParam) {
        this.id = MY_GLOBAL.nextId();
        this.name = nameParam;
        return this;
    },
    sayHello: function() {
        console.log('Hello '+ this.name);
    }
};

var bob = Object.create(userB).init('Bob');

Object.create를 사용할 수 있는 또 다른 방법은 값싸고 효과적인 방법으로 불변의 개체를 복제하는 것입니다.

var anObj = {
    a: "test",
    b: "jest"
};

var bObj = Object.create(anObj);

bObj.b = "gone"; // replace an existing (by masking prototype)
bObj.c = "brand"; // add a new to demonstrate it is actually a new obj

// now bObj is {a: test, b: gone, c: brand}

참고: 위의 스니펫은 소스 오브젝트의 클론을 만듭니다(cObj = aObj와 같이 참조가 아님).오브젝트 멤버 속성을 복사하지 않는다는 점에서 copy-properties 메서드(1 참조)보다 유리합니다.소스 객체에 설정된 프로토타입으로 다른 -destination 객체를 만듭니다.또한 대상 객체에서 속성이 수정되면 프로토타입(src)의 속성을 마스킹하여 "즉각"으로 생성됩니다.이것은 불변의 개체를 복제하는 효과적인 방법이 됩니다.

여기서 주의할 점은 이것이 작성 후 변경해서는 안 되는 소스 객체에 적용된다는 것입니다(불변).생성 후 소스 개체가 수정되면 모든 복제본의 마스킹되지 않은 속성도 수정됩니다.

여기를 클릭해 주세요(http://jsfiddle.net/y5b5q/1/) (Object.create capable browser 참조).

문제의은 - 이 차이를 합니다.new ★★★★★★★★★★★★★★★★★」Object.create접근합니다. 답변과 이 비디오에 따르면 new키워드는 다음 작업을 수행합니다.

  1. 새 개체를 만듭니다.

  2. 함수컨스트럭터 함수)에 합니다.prototype를 참조해 주세요.

  3. 내다this변수 포인트로 새 개체를 지정합니다.

  4. 으로 수행합니다.return this;

  5. 을 할당합니다.constructor.

Object.create은 ""뿐입니다.1st ★★★★★★★★★★★★★★★★★」2nd★★★★★★★★★★★★★★★★★★!

문제의 코드 예에서는 큰 문제가 되지 않지만 다음 예에서는 다음과 같습니다.

var onlineUsers = [];
function SiteMember(name) {
    this.name = name;
    onlineUsers.push(name);
}
SiteMember.prototype.getName = function() {
    return this.name;
}
function Guest(name) {
    SiteMember.call(this, name);
}
Guest.prototype = new SiteMember();

var g = new Guest('James');
console.log(onlineUsers);

부작용은 다음과 같습니다.

[ undefined, 'James' ]

Guest.prototype = new SiteMember();
할 필요는 됩니다.메서드만 만들면 됩니다.getName게스트에서 사용할 수 있습니다. 때문에 는 래를 사용해야 합니다.Object.create
를 치환하는 경우Guest.prototype = new SiteMember();
로로 합니다.Guest.prototype = Object.create(SiteMember.prototype);을 사용하다

[ 'James' ]

NEW를 사용하여 개체를 생성할 수 없지만 CREATE 메서드를 호출할 수 있는 경우가 있습니다.

예를 들어 커스텀 요소를 정의하려면 HTMLement에서 파생되어야 합니다.

proto = new HTMLElement  //fail :(
proto = Object.create( HTMLElement.prototype )  //OK :)
document.registerElement( "custom-element", { prototype: proto } )

은 ★★★★★입니다.Object.create으로 is is is is is보다 new

이 jsperf 예제에서는 Chromium에서 브라우저,new보다 30배 빠르다Object.create(obj)이데올로기이것은 모두 매우 이상합니다.이는 Object.create가 전달된 오브젝트를 프로토타입으로 사용하여 새로운 오브젝트를 작성해야 하기 때문입니다(Crockford-speak의 비밀 링크).

가 '만들기'를 것 .Object.create효율적이다.new에서도 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★」

요약:.

  • Object.create()자바스크립트.
  • 첫 번째 인수는 새로 생성된 객체의 프로토타입이 될 객체입니다.
  • 두 번째 인수는 새로 생성된 개체의 속성이 될 개체입니다.

예:

const proto = {
  talk : () => console.log('hi')
}

const props = {
  age: {
    writable: true,
    configurable: true,
    value: 26
  }
}


let Person = Object.create(proto, props)

console.log(Person.age);
Person.talk();

실용적인 응용 프로그램:

  1. 이 방법으로 객체를 작성하는 주된 장점은 프로토타입을 명시적으로 정의할 수 있다는 것입니다.오브젝트 리터럴을 사용하는 경우 또는new이 키워드는 사용자가 제어할 수 없습니다(단, 덮어쓸 수 있습니다).
  2. 을 갖고 싶다.new키워드는 컨스트럭터 함수를 호출합니다.★★★★★★★★★★★★★★★★ Object.create()생성자 함수를 호출하거나 선언할 필요가 없습니다.
  3. 기본적으로 매우 역동적인 방법으로 객체를 작성할 때 유용한 도구입니다.받은 인수에 따라 다른 프로토타입으로 객체를 생성하는 객체 팩토리 기능을 만들 수 있습니다.

.Object.create() 함수를 .Crockfords의 init.

이 조작은 유효합니다.

var userBPrototype = {
    init: function(nameParam) {
        this.name = nameParam;
    },
    sayHello: function() {
        console.log('Hello '+ this.name);
    }
};


function UserB(name) {
    function F() {};
    F.prototype = userBPrototype;
    var f = new F;
    f.init(name);
    return f;
}

var bob = UserB('bob');
bob.sayHello();

여기서 UserB는 Object.create와 비슷하지만 필요에 따라 조정됩니다.

필요한 경우 다음 번호로 전화할 수도 있습니다.

var bob = new UserB('bob');

Douglas Crockford는 Object.create()의 열렬한 지지자였으며 기본적으로 이 구성이 javascript에 있는 이유는 Douglas Crockford였지만 그는 더 이상 이 의견을 가지고 있지 않습니다.

Object.create가 너무 많은 문제를 일으키기 때문에 이 키워드를 사용하지 않게 되었습니다.예를 들어 주의하지 않으면 글로벌 객체를 쉽게 가리킬 수 있으며, 이는 매우 나쁜 결과를 초래할 수 있습니다.그리고 그는 이 Object.create를 사용하지 않으면 의미가 없다고 주장합니다.

2014년 Nordic.js에서 그가 강연하는 비디오를 확인하실 수 있습니다.

https://www.youtube.com/watch?v=PSGEjv3Tqo0

여기에 이미지 설명 입력

new ★★★★★★★★★★★★★★★★★」Object.create러러가가 목목목목목new는 오브젝트 유형의 새 인스턴스를 작성하는 것을 목적으로 합니다. Object.create단순히 새로운 객체를 만들고 프로토타입을 설정하기 위한 것입니다.게게왜 왜? ??? 을 실장하다__proto__오브젝트인스턴스라고 불립니다[[Prototype]]는 가상 머신의 내부 속성이며 직접 액세스하기 위한 것이 아닙니다. 할 수 유일한 [[Prototype]]__proto__이는 모든 주요 가상 머신의 ECMAScript 구현에 대한 사실상의 표준이며, 이 시점에서 ECMAScript를 제거하면 많은 기존 코드가 깨지기 때문입니다.

의한 로 7ochem의 는 안 .new스테이트먼트는 동일한 프로토타입 컨스트럭터를 여러 번 호출할 필요가 없을 뿐만 아니라 동일한 클래스의 두 인스턴스가 생성된 후 프로토타입을 수정하면 결국 다른 동작으로 끝날 수 있기 때문입니다.두 예 모두 단순히 프로토타입 상속 체인의 의도된 동작을 오해하고 파괴한 결과로 인한 잘못된 코드입니다.

접속하는 __proto__하려면 , 「인스턴스」를 사용해 Object.create 그 에 ★★★★★★★★★★★★★★★★★★★Object.setPrototypeOf , 로 .Object.getPrototypeOf ★★★★★★★★★★★★★★★★★」Object.isPrototypeOf.

또한 오브젝트의 Mozilla 문서로도 사용됩니다.setProtypeOf는 오브젝트 생성 후 오브젝트 프로토타입을 수정하는 것은 퍼포먼스상의 이유로 오브젝트 생성 후 오브젝트 프로토타입을 수정하는 것은 좋지 않다고 지적하고 있습니다.또한 오브젝트에 액세스하는 특정 코드가 변경되기 전에 오브젝트 프로토타입을 수정할 수 있는 경우 정의되지 않은 동작이 발생할 수 있습니다.단, c는 예외입니다.ode는 현재 프로토타입을 확인하거나 둘 사이에 차이가 있는 어떠한 속성에도 접근하지 않도록 매우 주의해야 합니다.

★★★★★★★★★★★★★★★★★」

const X = function (v) { this.v = v }; X.prototype.whatAmI = 'X'; X.prototype.getWhatIAm = () => this.whatAmI; X.prototype.getV = () => this.v;

의 VM 는, 「VM」의 합니다.const x0 = new X(1);:

const x0 = {}; x0.[[Prototype]] = X.prototype; X.prototype.constructor.call(x0, 1);

는 임의의할 수 만, 이 값은 할 수 .new된 오브젝트에대한 를 반환합니다.

다음 이에 해당합니다.const x1 = Object.create(X.prototype);:

const x0 = {}; x0.[[Prototype]] = X.prototype;

와 같이 이 은 '하다'라는 밖에 없습니다.Object.create도 반환할 수 오브젝트레퍼런스 「」를 할 뿐입니다.실제로 어떤 값도 반환할 수 있지만 단순히 새 개체 참조를 반환할 뿐입니다.this★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

다음 정의를 가진 서브클래스 Y를 작성하는 경우:

const Y = function(u) { this.u = u; } Y.prototype.whatAmI = 'Y'; Y.prototype.getU = () => this.u;

그럼 이렇게 X로부터 물려받으면 되겠네요__proto__:

Y.prototype.__proto__ = X.prototype;

할 수 , 「이렇게 하면」에 된다.__proto__ 라이선스:

Y.prototype = Object.create(X.prototype); Y.prototype.constructor = Y;

할 필요가 있습니다.new Y 않은 경우)new Y합니다.X가 원하는new YX에서 Y를 사용하는 이 더 것입니다.X.call(this, u)

new

  • 생성자 함수에서 개체를 만드는 데 사용됩니다.
  • new 함수도 합니다.
function Car() {
  console.log(this) // this points to myCar
  this.name = "Honda";
}

var myCar = new Car()
console.log(myCar) // Car {name: "Honda", constructor: Object}
console.log(myCar.name) // Honda
console.log(myCar instanceof Car) // true
console.log(myCar.constructor) // function Car() {}
console.log(myCar.constructor === Car) // true
console.log(typeof myCar) // object

Object.create

  • 이 경우에도 하실 수 있습니다.Object.create
  • 그러나 생성자 함수는 실행되지 않습니다.
  • Object.create 때 사용합니다.
const Car = {
  name: "Honda"
}

var myCar = Object.create(Car)
console.log(myCar) // Object {}
console.log(myCar.name) // Honda
console.log(myCar instanceof Car) // ERROR
console.log(myCar.constructor) // Anonymous function object
console.log(myCar.constructor === Car) // false
console.log(typeof myCar) // object

난 폐쇄적인 접근을 선호한다.

도 쓰고 요.new는 안 써요.Object.create는 안 써요.this.

도 쓰고 요.new나는 그것의 선언적인 성격을 좋아하기 때문입니다.

단순 상속으로 간주합니다.

window.Quad = (function() {

    function Quad() {

        const wheels = 4;
        const drivingWheels = 2;

        let motorSize = 0;

        function setMotorSize(_) {
            motorSize = _;
        }

        function getMotorSize() {
            return motorSize;
        }

        function getWheelCount() {
            return wheels;
        }

        function getDrivingWheelCount() {
            return drivingWheels;
        }
        return Object.freeze({
            getWheelCount,
            getDrivingWheelCount,
            getMotorSize,
            setMotorSize
        });
    }

    return Object.freeze(Quad);
})();

window.Car4wd = (function() {

    function Car4wd() {
        const quad = new Quad();

        const spareWheels = 1;
        const extraDrivingWheels = 2;

        function getSpareWheelCount() {
            return spareWheels;
        }

        function getDrivingWheelCount() {
            return quad.getDrivingWheelCount() + extraDrivingWheels;
        }

        return Object.freeze(Object.assign({}, quad, {
            getSpareWheelCount,
            getDrivingWheelCount
        }));
    }

    return Object.freeze(Car4wd);
})();

let myQuad = new Quad();
let myCar = new Car4wd();
console.log(myQuad.getWheelCount()); // 4
console.log(myQuad.getDrivingWheelCount()); // 2
console.log(myCar.getWheelCount()); // 4
console.log(myCar.getDrivingWheelCount()); // 4 - The overridden method is called
console.log(myCar.getSpareWheelCount()); // 1

피드백 장려.

언급URL : https://stackoverflow.com/questions/2709612/using-object-create-instead-of-new

반응형