자바 스크립트에서 [] 연산자를 오버로드하는 방법을 찾을 수없는 것 같습니다. 아는 사람 있어요?
나는 생각하고 있었다 ...
MyClass.operator.lookup(index)
{
return myArray[index];
}
아니면 내가 옳은 일을보고 있지 않습니까?
자바 스크립트에서 [] 연산자를 오버로드하는 방법을 찾을 수없는 것 같습니다. 아는 사람 있어요?
나는 생각하고 있었다 ...
MyClass.operator.lookup(index)
{
return myArray[index];
}
아니면 내가 옳은 일을보고 있지 않습니까?
MyClass
객체를 배열로 만드십시오 . 당신은에서 키와 값을 복사 할 수 있습니다 myArray
당신에 var myObj = new MyClass()
객체입니다.
답변:
Object arg1: a arg2: b arg3: c
가 Object["arg1:arg2:arg3:"](a,b,c)
. 당신은 할 수 있습니다 myObject["[]"](1024)
: P
target[name]
는 getter에서 반환 할 수 있습니다 . OP는 예제를 보여줍니다
[]
운영자와도 함께 작동합니다. btw :var key = 'world';
console.log(proxy[key]);
간단한 대답은 JavaScript가 대괄호를 통해 객체의 자식에 액세스 할 수 있도록 허용한다는 것입니다.
따라서 클래스를 정의 할 수 있습니다.
MyClass = function(){
// Set some defaults that belong to the class via dot syntax or array syntax.
this.some_property = 'my value is a string';
this['another_property'] = 'i am also a string';
this[0] = 1;
};
그러면 두 구문 중 하나를 사용하여 클래스의 모든 인스턴스에서 멤버에 액세스 할 수 있습니다.
foo = new MyClass();
foo.some_property; // Returns 'my value is a string'
foo['some_property']; // Returns 'my value is a string'
foo.another_property; // Returns 'i am also a string'
foo['another_property']; // Also returns 'i am also a string'
foo.0; // Syntax Error
foo[0]; // Returns 1
foo['0']; // Returns 1
foo['random']
코드가 할 수없는 것을 잡는 방법을 요구 하는 것입니다.
프록시를 사용하십시오. 답변의 다른 곳에서 언급되었지만 이것이 더 나은 예라고 생각합니다.
var handler = {
get: function(target, name) {
if (name in target) {
return target[name];
}
if (name == 'length') {
return Infinity;
}
return name * name;
}
};
var p = new Proxy({}, handler);
p[4]; //returns 16, which is the square of 4.
대괄호 연산자는 실제로 속성 액세스 연산자이므로 getter 및 setter로 연결할 수 있습니다. IE의 경우 대신 Object.defineProperty ()를 사용해야합니다. 예:
var obj = {
get attr() { alert("Getter called!"); return 1; },
set attr(value) { alert("Setter called!"); return value; }
};
obj.attr = 123;
IE8 +에서도 동일 :
Object.defineProperty("attr", {
get: function() { alert("Getter called!"); return 1; },
set: function(value) { alert("Setter called!"); return value; }
});
IE5-7의 onpropertychange
경우 이벤트 만 있으며 DOM 요소에는 작동하지만 다른 개체에는 작동하지 않습니다.
이 메서드의 단점은 미리 정의 된 이름이없는 임의의 속성이 아니라 미리 정의 된 속성 집합에 대한 요청 만 연결할 수 있다는 것입니다.
obj['any_key'] = 123;
하지만 코드에서 보는 것은 (아직 알려지지 않은) 키에 대해 setter / getter를 정의해야합니다. 그것은 불가능합니다.
설명대로 Proxy를 사용해야하지만 궁극적으로 클래스 생성자에 통합 될 수 있습니다.
return new Proxy(this, {
set: function( target, name, value ) {
...}};
'this'와 함께. 그러면 set 및 get (또한 deleteProperty) 함수가 실행됩니다. 비록 당신이 다른 것처럼 보이는 Proxy 객체를 얻더라도 그것은 대부분의 경우 비교 (target.constructor === MyClass)를 요청하기 위해 작동합니다. 그것은 클래스 유형 등입니다. 텍스트 (약간 다르게 작동하는 예를 언급합니다.)]
그래서 당신은 var whatever = MyClassInstance [4]; ? 그렇다면 간단한 대답은 Javascript가 현재 연산자 오버로딩을 지원하지 않는다는 것입니다.
이를 수행하는 한 가지 교활한 방법은 언어 자체를 확장하는 것입니다.
사용자 지정 인덱싱 규칙을 정의하고 "[]"라고 부르겠습니다.
var MyClass = function MyClass(n) {
this.myArray = Array.from(Array(n).keys()).map(a => 0);
};
Object.defineProperty(MyClass.prototype, "[]", {
value: function(index) {
return this.myArray[index];
}
});
...
var foo = new MyClass(1024);
console.log(foo["[]"](0));
새로운 평가 구현을 정의합니다. (이렇게하지 마십시오. 그러나 이것은 개념 증명입니다).
var MyClass = function MyClass(length, defaultValue) {
this.myArray = Array.from(Array(length).keys()).map(a => defaultValue);
};
Object.defineProperty(MyClass.prototype, "[]", {
value: function(index) {
return this.myArray[index];
}
});
var foo = new MyClass(1024, 1337);
console.log(foo["[]"](0));
var mini_eval = function(program) {
var esprima = require("esprima");
var tokens = esprima.tokenize(program);
if (tokens.length == 4) {
var types = tokens.map(a => a.type);
var values = tokens.map(a => a.value);
if (types.join(';').match(/Identifier;Punctuator;[^;]+;Punctuator/)) {
if (values[1] == '[' && values[3] == ']') {
var target = eval(values[0]);
var i = eval(values[2]);
// higher priority than []
if (target.hasOwnProperty('[]')) {
return target['[]'](i);
} else {
return target[i];
}
return eval(values[0])();
} else {
return undefined;
}
} else {
return undefined;
}
} else {
return undefined;
}
};
mini_eval("foo[33]");
위의 내용은 더 복잡한 인덱스에서는 작동하지 않지만 더 강력한 구문 분석을 사용할 수 있습니다.
고유 한 상위 집합 언어를 만드는 대신 기존 언어로 표기법을 컴파일 한 다음 평가할 수 있습니다. 이렇게하면 처음 사용한 후 구문 분석 오버 헤드가 네이티브로 줄어 듭니다.
var compile = function(program) {
var esprima = require("esprima");
var tokens = esprima.tokenize(program);
if (tokens.length == 4) {
var types = tokens.map(a => a.type);
var values = tokens.map(a => a.value);
if (types.join(';').match(/Identifier;Punctuator;[^;]+;Punctuator/)) {
if (values[1] == '[' && values[3] == ']') {
var target = values[0];
var i = values[2];
// higher priority than []
return `
(${target}['[]'])
? ${target}['[]'](${i})
: ${target}[${i}]`
} else {
return 'undefined';
}
} else {
return 'undefined';
}
} else {
return 'undefined';
}
};
var result = compile("foo[0]");
console.log(result);
console.log(eval(result));
우리는 얻을 수 있습니다 | 방법을 직접 설정하십시오 . 영감을받은 이 .
class Foo {
constructor(v) {
this.data = v
return new Proxy(this, {
get: (obj, key) => {
if (typeof(key) === 'string' && (Number.isInteger(Number(key)))) // key is an index
return obj.data[key]
else
return obj[key]
},
set: (obj, key, value) => {
if (typeof(key) === 'string' && (Number.isInteger(Number(key)))) // key is an index
return obj.data[key] = value
else
return obj[key] = value
}
})
}
}
var foo = new Foo([])
foo.data = [0, 0, 0]
foo[0] = 1
console.log(foo[0]) // 1
console.log(foo.data) // [1, 0, 0]