자바 스크립트에서 [] 연산자를 어떻게 오버로드 하시겠습니까?
자바 스크립트에서 [] 연산자를 오버로드하는 방법을 찾을 수없는 것 같습니다. 아는 사람 있어요?
나는 생각하고 있었다 ...
MyClass.operator.lookup(index)
{
return myArray[index];
}
아니면 내가 옳은 일을보고 있지 않습니까?
JavaScript에서는 연산자를 오버로드 할 수 없습니다.
ECMAScript 4 용 으로 제안 되었지만 거부되었습니다.
조만간 볼 수 없을 것 같습니다.
ES6 프록시 ( 모든 최신 브라우저 에서 사용 가능)로이 작업을 수행 할 수 있습니다.
var handler = {
get: function(target, name) {
return "Hello, " + name;
}
};
var proxy = new Proxy({}, handler);
console.log(proxy.world); // output: Hello, world
MDN에 대한 자세한 내용을 확인하십시오 .
간단한 대답은 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
프록시를 사용하십시오. 답변의 다른 곳에서 언급되었지만 이것이 더 나은 예라고 생각합니다.
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 요소에는 작동하지만 다른 개체에는 작동하지 않는 이벤트 만 있습니다.
이 메서드의 단점은 미리 정의 된 이름이없는 임의의 속성이 아니라 미리 정의 된 속성 집합에 대한 요청 만 연결할 수 있다는 것입니다.
그래서 당신은 var whatever = MyClassInstance [4]; ? 그렇다면 간단한 대답은 Javascript가 현재 연산자 오버로딩을 지원하지 않는다는 것입니다.
설명대로 Proxy를 사용해야하지만 궁극적으로 클래스 생성자에 통합 될 수 있습니다.
return new Proxy(this, {
set: function( target, name, value ) {
...}};
'this'와 함께. 그러면 set 및 get (또한 deleteProperty) 함수가 실행됩니다. 다르게 보이는 프록시 객체를 얻더라도 대부분의 경우 비교 (target.constructor === MyClass)를 요청하는 작업을 수행합니다. 클래스 유형 등입니다. [target.constructor.name이 클래스 이름 인 함수 임에도 불구하고 텍스트 (약간 다르게 작동하는 예를 언급합니다.)]
이를 수행하는 한 가지 교활한 방법은 언어 자체를 확장하는 것입니다.
1 단계
사용자 지정 인덱싱 규칙을 정의하고 "[]"라고 부르겠습니다.
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));
2 단계
새로운 평가 구현을 정의합니다. (이렇게하지 마십시오. 그러나 이것은 개념 증명입니다).
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]");
위의 내용은 더 복잡한 인덱스에서는 작동하지 않지만 더 강력한 구문 분석을 사용할 수 있습니다.
대안 :
instead of resorting to creating your own superset language, you can instead compile your notation to the existing language, then eval it. This reduces the parsing overhead to native after the first time you use it.
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));
We can proxy get | set methods directly. Inspired by this.
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]
참고URL : https://stackoverflow.com/questions/1711357/how-would-you-overload-the-operator-in-javascript
'programing tip' 카테고리의 다른 글
소켓 프로그래밍을위한 INADDR_ANY 이해 (0) | 2020.10.26 |
---|---|
디스플레이없이 고정 높이의 입력 필드 내에서 텍스트를 세로로 정렬 : 테이블 또는 패딩? (0) | 2020.10.26 |
openssl에서“unable to write 'random state'”수정 방법 (0) | 2020.10.26 |
Java KeyStore에서 개인 키 / 공개 인증서 쌍 가져 오기 (0) | 2020.10.26 |
WGET 시간이 초과됩니까? (0) | 2020.10.26 |