Cet article résume et présente la méthode d'implémentation de la surcharge d'opérateurs en Javascript. L'idée d'implémentation est très simple. Les amis qui en ont besoin peuvent y jeter un œil
J'ai récemment effectué du traitement de données et personnalisé certaines structures de données. Par exemple, Mat, Vector, Point, etc., les quatre opérations arithmétiques telles que l'addition, la soustraction, la multiplication et la division doivent être définies à plusieurs reprises. Le code n'est pas très intuitif. Il est vraiment ennuyeux que JavaScript n'ait pas de surcharge d'opérateurs comme. C++ et C#, j'ai donc pensé que "Courbe pour sauver le pays" implémente automatiquement la surcharge d'opérateurs dans le code de traduction. L'idée d'implémentation est en fait très simple, elle consiste à écrire un interpréteur et à compiler le code. Par exemple :
S = A + B (B - C.fun())/2 + D
est traduit par
` S = remplacer(remplacer(A, '+', remplacer(remplacer(B,'',(remplacer(B,'-',C.fun())))),'/',2),' +' ,D)`
Dans la fonction de remplacement, nous appelons la fonction opérateur correspondante de l'objet. Le code de la fonction de remplacement est le suivant :
/** * 转换方法 * @param a * @param op * @param b * @returns {*} * @private */ export function __replace__(a,op,b){ if(typeof(a) != 'object' && typeof(b) != 'object'){ return new Function('a','b','return a' + op + 'b')(a,b) } if(!Object.getPrototypeOf(a).isPrototypeOf(b) && Object.getPrototypeOf(b).isPrototypeOf(a)){ throw '不同类型的对象不能使用四则运算' } let target = null if (Object.getPrototypeOf(a).isPrototypeOf(b)) { target = new Function('return ' + b.__proto__.constructor.name)() } if (Object.getPrototypeOf(b).isPrototypeOf(a)) { target = new Function('return ' + a.__proto__.constructor.name)() } if (op == '+') { if (target.__add__ != undefined) { return target.__add__(a, b) }else { throw target.toString() +'\n未定义__add__方法' } }else if(op == '-') { if (target.__plus__ != undefined) { return target.__plus__(a, b) }else { throw target.toString() + '\n未定义__plus__方法' } }else if(op == '*') { if (target.__multiply__ != undefined) { return target.__multiply__(a, b) }else { throw target.toString() + '\n未定义__multiply__方法' } } else if (op == '/') { if (target.__pide__ != undefined) { return target.__pide__(a, b) }else { throw target.toString() + '\n未定义__pide__方法' } } else if (op == '%') { if (target.__mod__ != undefined) { return target.__mod__(a, b) }else { throw target.toString() + '\n未定义__mod__方法' } } else if(op == '.*') { if (target.__dot_multiply__ != undefined) { return target.__dot_multiply__(a, b) }else { throw target.toString() + '\n未定义__dot_multiply__方法' } } else if(op == './') { if (target.__dot_pide__ != undefined) { return target.__dot_pide__(a, b) }else { throw target.toString() + '\n未定义__dot_pide__方法' } } else if(op == '**') { if (target.__power__ != undefined) { return target.__power__(a, b) }else { throw target.toString() + '\n未定义__power__方法' } }else { throw op + '运算符无法识别' } }
2 Parcourez le méta-tableau
Si l'élément est ')', extrayez l'élément de la pile, épissez-le jusqu'à ce qu'il rencontre '(', et placez-le dans la pile. Ici, vous devez faire attention à savoir si l'élément '(' est précédé d'un appel de fonction ou d'un remplacement. S'il s'agit d'un appel ou d'un remplacement de fonction, vous devez continuer à faire avancer les données et fermer le remplacement. fonction.
S'il s'agit d'un élément général, vérifiez si l'élément précédent remplace, si c'est le cas, vous devez épisser ')' pour fermer la fonction de remplacement, sinon poussez l'élément directement sur la pile
<. 🎜>
/** * 表达式转换工具方法 * @param code */ export function translate (code) { let data = [] let tmp_code = code.replace(/\s/g,'') let tmp = [] let vari = tmp_code.split(/["]+[^"]*["]+|[']+[^']*[']+|\*\*|\+|-|\*|\/|\(|\)|\?|>[=]|<[=]|={2}|:|&{2}|\|{2}|\{|\}|=|%|\.\/|\.\*|,/g) let ops = tmp_code.match(/["]+[^"]*["]+|[']+[^']*[']+|\*\*|\+|-|\*|\/|\(|\)|\?|>[=]|<[=]|={2}|:|&{2}|\|{2}|\{|\}|=|%|\.\/|\.\*|,/g) for (let i = 0,len = ops.length; i < len; i++) { if (vari[i] != '') { tmp.push(vari[i]) } if (ops[i] != '') { tmp.push(ops[i]) } } tmp.push(vari[ops.length]) for (let i = 0; i < tmp.length; i++){ let item = tmp[i] if(/\*\*|\+|-|\*|\/|%|\.\/|\.\*/.test(tmp[i])) { let top = data.pop() let trans = '__replace__(' + top + ',\'' + tmp[i] + '\',' data.push(trans) }else{ if (')' == tmp[i]) { let trans0 = tmp[i] let top0 = data.pop() while (top0 != '(') { trans0 = top0 + trans0 top0 = data.pop() } trans0 = top0 + trans0 let pre = data[data.length - 1] while(/[_\w]+[\.]?[_\w]+/.test(pre) && !/^__replace__\(/.test(pre) && pre != undefined) { pre = data.pop() trans0 = pre + trans0 pre = data[data.length - 1] } pre = data[data.length - 1] while(pre != undefined && /^__replace__\(/.test(pre)){ pre = data.pop() trans0 = pre + trans0 + ')' pre = data[data.length - 1] } data.push(trans0) }else { let pre = data[data.length - 1] let trans1 = tmp[i] while(pre != undefined && /^__replace__\(/.test(pre) && !/\*\*|\+|-|\*|\/|\(|\?|>[=]|<[=]|={2}|:|&{2}|\|{2}|\{|=|\}|%|\.\/|\.\*/.test(item) && !/^__replace__\(/.test(item)) { if(tmp[i + 1] == undefined){ pre = data.pop() trans1 = pre + trans1 + ')' break; }else{ pre = data.pop() trans1 = pre + trans1 + ')' pre = data[data.length - 1] } } data.push(trans1) } } } let result = '' data.forEach((value, key, own) => { result += value }) return result }
La méthode de compilation d'expression est écrite. Suivant Voilà comment faire traduire le code écrit par notre traducteur, c'est-à-dire qu'un conteneur est nécessaire, et deux méthodes : l'une consiste à redéfinir la méthode. attributs avec le constructeur de classe, et l'autre consiste à transmettre le code en tant que paramètre dans notre méthode personnalisée. Ensuite, introduisons la méthode de redéfinition dans le constructeur de classe :
<. 🎜>export default class OOkay { constructor () { let protos = Object.getOwnPropertyNames(Object.getPrototypeOf(this)) protos.forEach((proto, key, own) => { if(proto != 'constructor'){ Object.defineProperty(this, proto, { value:new Function(translate_block(proto, this[proto].toString())).call(this) }) } }) } }
.
/** * 类代码块转换工具 * @param name * @param block * @returns {string} */ export function translate_block (name , block) { let codes = block.split('\n') let reg = new RegExp('^' + name + '$') console.log(reg.source) codes[0] = codes[0].replace(name,'function') for(let i = 1; i < codes.length; i++) { if (codes[i].indexOf('//') != -1) { codes[i] = codes[i].substring(0,codes[i].indexOf('//')) } if(/\*\*|\+|-|\*|\/|%|\.\/|\.\*/g.test(codes[i])){ if (codes[i].indexOf('return ') != -1) { let ret_index = codes[i].indexOf('return ') + 7 codes[i] = codes[i].substring(0,ret_index) + translate(codes[i].substring(ret_index)) }else { let eq_index = codes[i].indexOf('=') + 1 codes[i] = codes[i].substring(0,eq_index) + translate(codes[i].substring(eq_index)) } } } return 'return ' + codes.join('\n') }
/** * 非继承类的注入方法 * @param target */ static inject (target) { let protos = Object.getOwnPropertyNames(Object.getPrototypeOf(target)) protos.forEach((proto, key, own) => { if (proto != 'constructor') { Object.defineProperty(target, proto, { value:new Function(translate_block(proto, target[proto].toString())).call(target) }) } }) }
L'autre consiste à transmettre le code comme un paramètre dans la méthode __$$__, qui compile le code et l'exécute, comme suit :
static __$__(fn) { if(!(fn instanceof Function)){ throw '参数错误' } (new Function(translate_block('function',fn.toString()))).call(window)() }
Comment résoudre les caractères chinois tronqués lorsque JQuery ajax renvoie json
Comment utiliser la méthode post d'ajax dans le framework Django
django Solution à l'erreur 403 lors de l'utilisation des données de publication jquery ajax
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!