javaScript로 나열하지 않고 매개 변수의 값 배열을 사용하여 객체를 어떻게 구성 할 수 있습니까?

StackOverflow https://stackoverflow.com/questions/813383

문제

이게 가능해? 나는 다른 유형의 공장을 구동하기 위해 단일 기본 공장 기능을 만들고 있지만 (유사점이 있지만) 인수를 기본 공장에 배열로 전달할 수있게되면서 인수를 채우는 새로운 객체의 인스턴스를 만들 수 있습니다. 배열을 통한 관련 클래스의 생성자.

JavaScript에서는 배열을 사용하여 적용 메소드를 사용하여 여러 인수가있는 함수를 호출 할 수 있습니다.

namespace.myFunc = function(arg1, arg2) { //do something; }
var result = namespace.myFunc("arg1","arg2");
//this is the same as above:
var r = [ "arg1","arg2" ];
var result = myFunc.apply(namespace, r);

어쨌든 적용을 사용하여 객체 인스턴스를 만드는 것처럼 보이지는 않습니다.

(이것은 작동하지 않습니다) : :

var instance = new MyClass.apply(namespace, r);
도움이 되었습니까?

해결책

이 시도:

var instance = {};
MyClass.apply( instance, r);

모든 키워드 "New"는 새 객체를 생성자에게 전달하여 생성자 함수 내부 의이 변수가됩니다.

생성자 작성 방법에 따라 다음을 수행해야 할 수도 있습니다.

var instance = {};
var returned = MyClass.apply( instance, args);
if( returned != null) {
    instance = returned;
}

업데이트 : 의견에 따르면 프로토 타입이 있으면 작동하지 않습니다. 이 시도.

function newApply(class, args) {
    function F() {
        return class.apply(this, args);
    }
    F.prototype = class.prototype;
    return new F();
}

newApply( MyClass, args);

다른 팁

주목하십시오

  • new myClass()
    

    생성자 함수가 인수의 존재에 의존 할 수 있기 때문에 어떤 인수도 실패 할 수 있습니다.

  • myClass.apply(something, args)
    

    많은 경우, 특히 날짜 나 번호와 같은 기본 클래스에서 호출되는 경우에 실패합니다.

나는 "평가가 악하다"라는 것을 알고 있지만이 경우 다음을 시도하고 싶을 수도 있습니다.

function newApply(Cls, args) {
    var argsWrapper = [];
    for (var i = 0; i < args.length; i++) {
        argsWrapper.push('args[' + i + ']');
    }
    eval('var inst = new Cls(' + argsWrapper.join(',') + ');' );
    return inst;
}

그렇게 간단합니다.

(그것은 동일하게 작동합니다 Instance.New 안에 이 블로그 게시물)

해킹은 해킹이지만 해킹은 해킹이지만, 아마도 구문을 호출하는 것은 당신이 원하는 것과 비슷하고 원본 클래스를 전혀 수정할 필요가 없기 때문에 다른 것들보다 약간 우아 할 것입니다.

Function.prototype.build = function(parameterArray) {
    var functionNameResults = (/function (.{1,})\(/).exec(this.toString());
    var constructorName = (functionNameResults && functionNameResults.length > 1) ? functionNameResults[1] : "";
    var builtObject = null;
    if(constructorName != "") {
       var parameterNameValues = {}, parameterNames = [];
       for(var i = 0; i < parameterArray.length; i++) {
         var parameterName = ("p_" + i);
         parameterNameValues[parameterName] = parameterArray[i];
         parameterNames.push(("parameterNameValues." + parameterName));
       }
       builtObject = (new Function("parameterNameValues", "return new " + constructorName + "(" + parameterNames.join(",") + ");"))(parameterNameValues);
    }
    return builtObject;
};

이제 객체를 만들기 위해이 중 하나를 수행 할 수 있습니다.

var instance1 = MyClass.build(["arg1","arg2"]);
var instance2 = new MyClass("arg1","arg2");

물론, 일부는 기능 개체의 프로토 타입을 수정하는 것을 좋아하지 않을 수도 있으므로 이런 식으로 수행하고 대신 기능으로 사용할 수 있습니다.

function build(constructorFunction, parameterArray) {
    var functionNameResults = (/function (.{1,})\(/).exec(constructorFunction.toString());
    var constructorName = (functionNameResults && functionNameResults.length > 1) ? functionNameResults[1] : "";
    var builtObject = null;
    if(constructorName != "") {
       var parameterNameValues = {}, parameterNames = [];
       for(var i = 0; i < parameterArray.length; i++) {
         var parameterName = ("p_" + i);
         parameterNameValues[parameterName] = parameterArray[i];
         parameterNames.push(("parameterNameValues." + parameterName));
       }
       builtObject = (new Function("parameterNameValues", "return new " + constructorName + "(" + parameterNames.join(",") + ");"))(parameterNameValues);
    }
    return builtObject;
};

그런 다음 그렇게 부릅니다.

var instance1 = build(MyClass, ["arg1","arg2"]);

따라서 이것이 누군가에게 유용하기를 바랍니다. 원래 생성자 기능을 단독으로 남겨두고 하나의 간단한 코드 라인 (현재 선택된 솔루션/해결 방법에 필요한 두 줄과 달리)을 얻을 수 있습니다.

피드백을 환영하고 감사합니다.


업데이트 : 하나의 다른 방법 - 이러한 다른 방법으로 동일한 유형의 인스턴스를 작성한 다음 생성자 속성이 동일한 지 확인하십시오. 물체. 내 말은 다음 코드로 가장 잘 설명됩니다.

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

var p1 = new Person("John", "Doe");
var p2 = Person.build(["Sara", "Lee"]);

var areSameType = (p1.constructor == p2.constructor);

다른 해킹 중 일부와 함께 시도하고 무슨 일이 일어나는지 확인하십시오. 이상적으로는 동일한 유형이되기를 원합니다.


경고 : 의견에 언급 된 바와 같이, 이것은 익명 함수 구문을 사용하여 생성 된 생성자 기능에 대해서는 작동하지 않습니다.

MyNamespace.SomeClass = function() { /*...*/ };

하지 않는 한 당신은 다음과 같이 만듭니다.

MyNamespace.SomeClass = function SomeClass() { /*...*/ };

위에서 제공 한 솔루션은 귀하에게 유용 할 수도 있고 아닐 수도 있습니다. 귀하는 귀하의 특정 요구에 대한 최상의 솔루션에 도달하기 위해 수행하는 일을 정확하게 이해해야하며, 내 솔루션을 만들기 위해 무슨 일이 일어나고 있는지 인식해야합니다. " 일하다." 내 솔루션이 어떻게 작동하는지 이해하지 못하면 시간을 보내십시오.


대체 솔루션 : 다른 옵션을 간과 할 사람이 아니라, 여기 에이 고양이를 피부에 뿌릴 수있는 다른 방법 중 하나가 있습니다 (위의 접근 방식과 비슷한 경고로), 이것은 조금 더 난해합니다.

function partial(func/*, 0..n args */) {
   var args = Array.prototype.slice.call(arguments, 1);
   return function() {
      var allArguments = args.concat(Array.prototype.slice.call(arguments));
      return func.apply(this, allArguments);
   };
}

Function.prototype.build = function(args) {
   var constructor = this;
   for(var i = 0; i < args.length; i++) {
      constructor = partial(constructor, args[i]);
   }
   constructor.prototype = this.prototype;
   var builtObject = new constructor();
   builtObject.constructor = this;
   return builtObject;
};

즐기다!

해결 방법은 어떻습니까?

function MyClass(arg1, arg2) {

    this.init = function(arg1, arg2){
        //if(arg1 and arg2 not null) do stuff with args
    }

    init(arg1, arg2);
}

그래서 당신은 어떻게 할 수 있는지 :

var obj = new MyClass();
obj.apply(obj, args);

한 가지 가능성은 생성자가 일반 함수 호출로 작동하도록하는 것입니다.

function MyClass(arg1, arg2) {
    if (!(this instanceof MyClass)) {
        return new MyClass(arg1, arg2);
    }

    // normal constructor here
}

상태의 조건 if 당신이 전화하면 진술이 사실이 될 것입니다 MyClass 정상적인 기능으로 ( call/apply 길이 this 논쟁은 아닙니다 MyClass object).

이제이 모든 것이 동일합니다.

new MyClass(arg1, arg2);
MyClass(arg1, arg2);
MyClass.call(null, arg1, arg2);
MyClass.apply(null, [arg1, arg2]);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top