javaScript로 나열하지 않고 매개 변수의 값 배열을 사용하여 객체를 어떻게 구성 할 수 있습니까?
-
03-07-2019 - |
문제
이게 가능해? 나는 다른 유형의 공장을 구동하기 위해 단일 기본 공장 기능을 만들고 있지만 (유사점이 있지만) 인수를 기본 공장에 배열로 전달할 수있게되면서 인수를 채우는 새로운 객체의 인스턴스를 만들 수 있습니다. 배열을 통한 관련 클래스의 생성자.
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]);