2014-02-14 2 views
2

생성자 생성자를 만들고 싶습니다. 이 스레드에 관한 : JavaScript build a constructor of constructors 것 같습니다 유일한 해결 방법은 다음과 같습니다더 좋은 방법은 함수 프로토 타입을 수정하는 것입니다.

Function.prototype.add = function(name, value) { 
    this.prototype[name] = value; 
}; 
Function.prototype.remove = function(name) { 
    delete this.prototype[name]; 
}; 

하지만 일반 Function 프로토 타입을 수정하려면 ...도하지 않습니다

var A = new ConstBuilder().add('test', function() { 
    console.log('test'); 
}).getConstructor(); 

하지만 돈 생성자 주위에 객체 래퍼가 있어야합니다.

일반적으로 생성자는 생성자 프로토 타입에서 메서드를 상속하는 새 개체를 만듭니다. 난 할 노력하고있어하는 대신 객체의 instanciates 기능을하지만, 함수 프로토 타입 속성을 수정하는 유일한 방법이이 __proto__ 속성을 수정하는 것입니다 :A.prototype

var constructorPrototype = { 
    add : function(name, value) { 
     this.prototype[name] = value ; 
    } 
} ; 

var ConstBuilder = function() { 
    var constructor = function() {} ; 
    constructor.prototype = {} ; 
    // The only way (?), but quite deprecated... 
    constructor.__proto__ = constructorPrototype ; 
    return constructor ; 
} ; 

// Not working way... 
//ConstBuilder.prototype = constructorPrototype ; 

var A = new ConstBuilder() ; 
A.add('test', function() { 
    console.log('test') ; 
}) ; 

var a = new A() ; 
a.test() ; // "test" 

constructorPrototype.remove : function() { 
    delete this.prototype[name] ; 
} ; 

A.remove('test') ; 

a.test() ; // Error: test is not a function. 

참고하지 A.__proto__하지만,A.prototype(new A).__proto__입니다.

__proto__을 수정하면 완벽하게 작동합니다. Firefox에 "Object.setPrototypeOf()"가 통합되어 있지만 읽기 전용입니다.

제가하고 싶은 일을하는 또 다른 방법이 있습니까?

+0

a.constructor.prototype == a .__ proto__, 브라우저 간 구현에 도움이되는 link.does를 중단하지 않는 한? – dandavis

+0

수정하고있는'a .__ proto'가 아니며'ConstBuilder'가 새로운 인스턴스를 반환하는 대신 직접 반환하기 때문에'A.__ proto__'는 함수이고'ConstBuilder'의 인스턴스가 아닙니다. – Tot

+0

죄송합니다. 귀하의 코드에서 "a"를 사용했는지 알지 못했습니다. 나는 광범위하게 말하고 있었다. 그래서, X.constructor.prototype == X.__ proto__ – dandavis

답변

7

실제로. 원하는 작업을 수행하는 유일한 방법은 반환 할 함수의 __proto__ 속성을 변경하는 것입니다. 그러나 그것은 나쁜 것이 아닙니다. 실제로 ES6 Harmony는 이것을 Object.setPrototypeOf 기능으로 표준화하려고합니다.

그러나 나는 매우 느리게 프로그램을 만들기 때문에 개체의 [[Prototype]] 변이에 대해 조언했다. 가능한 빠른 대안이있다 :

는 전통적으로 프로토 타입 객체의 특정 유형에서 작동하는 함수를 정의하는 데 사용되는 프로토 타입

를 사용하지 마십시오. 특정 인수를 전문으로하는 이러한 함수를 메소드라고합니다.

예를 들어 obj.func(a, b, c)objobj의 인스턴스를 전문으로합니다. 반면에 func(obj, a, b, c)은 어떤 인수에도 맞지 않습니다 (즉, obj은 어떤 값이 될 수도 있음).

function add(func, name, value) { 
    func.prototype[name] = value; 
} 

function remove(func, name) { 
    delete func.prototype[name]; 
} 

지금 당신은 당신이 원하는 모든 기능을 addremove를 사용할 수 있습니다 다음과 같이 addremove를 다시 작성할 수있는 예제 다음

. 당신은 상속에 대해 전혀 걱정할 필요가 없습니다.

유일한 문제는 네임 스페이스 충돌입니다. add이라는 함수가 있다고 가정 해보십시오. 어떻게합니까? 대답은 꽤 간단합니다.새 네임 스페이스를 만듭니다.

Function.add = function (func, name, value) { 
    func.prototype[name] = value; 
}; 

Function.remove = function remove(func, name) { 
    delete func.prototype[name]; 
}; 

실제로 네이티브 JavaScript API가 일반적으로하는 일입니다. 예를 들면 :

  1. Object.create
  2. Object.getPrototypeOf
  3. Object.setPrototypeOf

등등 등등.

요점은 다음과 같습니다. 일반화는 항상 전문화보다 낫습니다. 우리는 프로토 타입을 사용하여 전문화합니다. 우리는 일반화를 위해 일반 함수를 사용합니다. 일반화의 많은 장점은 전문성에 걸쳐 있습니다

  1. 당신은 call 같은 방법을 필요로하고 apply에 "unspecialize" 전문 기능하지 않습니다.
  2. 상속 및 프로토 타입 체인에 대해 걱정할 필요가 없습니다.
  3. 코드가보다 명확하고 이해하기 쉽습니다.

이것이 내가 전문화보다 일반화를 선호하는 이유입니다. 내가 프로토 타입을 사용하는 유일한 이유는 유니온 타입을 만드는 것입니다. 예를 들어 :

대신 추가하는 방법
function Shape(constructor) { 
    this.constructor = constructor; 
} 

function Circle(x, y, r) { 
    this.x = x; 
    this.y = y; 
    this.r = r; 
} 

function Rectangle(x1, y1, x2, y2) { 
    this.x1 = x1; 
    this.y1 = y1; 
    this.x2 = x2; 
    this.y2 = y2; 
} 

Circle.prototype = new Shape(Circle); 
Rectangle.prototype = new Shape(Rectangle); 

Circle.prototypeRectangle.prototype 나는 대신 다음을 수행하십시오

Circle.area = function (circle) { 
    return Math.PI * circle.r * circle.r; 
}; 

Rectangle.area = function (rectangle) { 
    return Math.abs((rectangle.x2 - rectangle.x1) * (rectangle.y2 - rectangle.y1)); 
}; 

Shape.prototype.area = function() { 
    return this.constructor.area(this); 
}; 

지금 대신 Circle.prototype.area.call(notCircleInstance)Circle.area(notCircleInstance)를 사용할 수 있습니다. 그것은 윈 - 윈 상황입니다. 일반화는 항상 전문화보다 낫습니다.

+0

고마워요, 이것은 제가 찾던 답변입니다. 나는 돌연변이'__proto__'가 느리다는 것을 안다. 그러나 나는 왜 그런지 모른다. 왜 그렇게 느린 지 말해 줄 수 있습니까? 그리고 나는 새로운 생성자를 수정하기 위해 다른 함수를 추가하는 모듈화 가능한 프레임 워크를 만들고 있기 때문에 이러한 메소드를 일반화하고 싶지 않습니다 ('add','remove'). 자유롭게 생각하면 좋지 않습니다. 'Function' 프로토 타입을 수정하십시오. 나는이 두 가지 기능을 주었지만 실제로 생성자가 사용하는 다른 열 개가 거의 10 개가 있습니다. 모든 기능에 "적용 가능"하지 않아서 생성자를 일반화하는 것이 지저분 할 것입니다. – Tot

+0

계속 하시려면 : http://stackoverflow.com/questions/21840926/javascript-why-manipulating-proto-is-slow – Tot

관련 문제