Home Web Front-end JS Tutorial How to implement operator overloading in JS

How to implement operator overloading in JS

May 02, 2018 am 10:31 AM
javascript accomplish operator

This time I will show you how to implement operator overloading in JS, and what are the notes for implementing operator overloading in JS. The following is a practical case, let’s take a look.

I have been doing data processing recently, and I have customized some data structures, such as Mat, Vector, Point, etc. I have to repeatedly define the four arithmetic operations such as addition, subtraction, multiplication and division. The code is not very intuitive, javascript The lack of operator overloading in C and C# is really frustrating, so I wanted to "save the country" by automatically implementing operator overloading in the translation code. The implementation idea is actually very simple, which is to write an interpreter and compile the code. For example:

S ​​= A B (B - C.fun())/2 D

is translated into

`S = replace(replace(A, ' ', replace( replace(B,'',(replace(B,'-',C.fun())))),'/',2),' ',D)`

In the replace function we Call the corresponding operator function of the object. The replace function code is as follows:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

/**

 * 转换方法

 * @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 + '运算符无法识别'

  }

}

Copy after login

The implementation of replacement is very simple. Without too much explanation, the important part is how to compile the code. The implementation of the four arithmetic operations when studying data structure in college is the basis of this translation, with slight differences. Briefly describe the process:

1. Split the expression, extract variables and operators to obtain the metaarray A
2. Traverse the metaarray

If the elements are operators addition, subtraction, multiplication and division, then from Pop the previous element from the stack and convert it to replace(last, operator,
If the element is ')', pop the element from the stack, splice it until it encounters '(', and push it into the stack. You need to pay attention here' ('Whether there is a function call or replace before the element. If it is a function call or replace, you need to continue to pop the data forward and close the replacement function.
If it is a general element, check whether the previous element is replaced. If so , you need to splice ')' to close the replace function, otherwise push the elements directly onto the stack

3. Combine the stack sequence obtained in step 2 to get the compiled expression

##. #According to the above process, implement the code:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

/**

 * 表达式转换工具方法

 * @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(/["]+[^"]*["]+|[&#39;]+[^&#39;]*[&#39;]+|\*\*|\+|-|\*|\/|\(|\)|\?|>[=]|<[=]|={2}|:|&{2}|\|{2}|\{|\}|=|%|\.\/|\.\*|,/g)

  for (let i = 0,len = ops.length; i < len; i++) {

    if (vari[i] != &#39;&#39;) {

      tmp.push(vari[i])

    }

    if (ops[i] != &#39;&#39;) {

      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 = &#39;replace(&#39; + top + &#39;,\&#39;&#39; + tmp[i] + &#39;\&#39;,&#39;

      data.push(trans)

    }else{

      if (&#39;)&#39; == tmp[i]) {

        let trans0 = tmp[i]

        let top0 = data.pop()

        while (top0 != &#39;(&#39;) {

          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 + &#39;)&#39;

          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 + &#39;)&#39;

            break;

          }else{

            pre = data.pop()

            trans1 = pre + trans1 + &#39;)&#39;

            pre = data[data.length - 1]

          }

        }

        data.push(trans1)

      }

    }

  }

  let result = &#39;&#39;

  data.forEach((value, key, own) => {

    result += value

  })

  return result

}

Copy after login
The expression compilation method has been written. The next step is how to make the written code translated by our translator, which means a container is needed. Two methods: one One is to redefine the method attributes in the class constructor, and the other is to pass the code as a parameter to our custom method. Next, we will introduce the redefined method in the class constructor:

1

2

3

4

5

6

7

8

9

10

11

12

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)

        })

      }

    })

  }

}

Copy after login
As can be seen from the above. , we use Object.defineProperty to redefine it in the constructor. translate_block is to divide the entire code block and translate it. The code is as follows:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

/**

 * 类代码块转换工具

 * @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(&#39;//&#39;) != -1) {

      codes[i] = codes[i].substring(0,codes[i].indexOf(&#39;//&#39;))

    }

    if(/\*\*|\+|-|\*|\/|%|\.\/|\.\*/g.test(codes[i])){

      if (codes[i].indexOf(&#39;return &#39;) != -1) {

        let ret_index = codes[i].indexOf(&#39;return &#39;) + 7

        codes[i] = codes[i].substring(0,ret_index) + translate(codes[i].substring(ret_index))

      }else {

        let eq_index = codes[i].indexOf(&#39;=&#39;) + 1

        codes[i] = codes[i].substring(0,eq_index) + translate(codes[i].substring(eq_index))

      }

    }

  }

  return &#39;return &#39; + codes.join(&#39;\n&#39;)

}

Copy after login

For new classes, we only need to inherit the OOkay class to

Use operator overloading. For those that inherit from non-OOkay classes, we can use injection, as follows:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

/**

   * 非继承类的注入方法

   * @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)

        })

      }

    })

  }

Copy after login
For code in non-classes, we need a container, here I used two methods, one is using ookay script, like this


Another option is to pass the code as a parameter into the $$ method, which compiles the code and executes it, as follows:

1

2

3

4

5

6

static $(fn) {

    if(!(fn instanceof Function)){

      throw '参数错误'

    }

    (new Function(translate_block('function',fn.toString()))).call(window)()

  }

Copy after login
I believe you have mastered the method after reading the case in this article, and more Please pay attention to other related articles on php Chinese website!

Recommended reading:

##How vue-cli makes cross-domain requests

## Detailed explanation of the steps to automatically build rem for webpack mobile terminal


detailed explanation of the steps of nodejs rendering page through response writeback

The above is the detailed content of How to implement operator overloading in JS. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How to implement dual WeChat login on Huawei mobile phones? How to implement dual WeChat login on Huawei mobile phones? Mar 24, 2024 am 11:27 AM

How to implement dual WeChat login on Huawei mobile phones? With the rise of social media, WeChat has become one of the indispensable communication tools in people's daily lives. However, many people may encounter a problem: logging into multiple WeChat accounts at the same time on the same mobile phone. For Huawei mobile phone users, it is not difficult to achieve dual WeChat login. This article will introduce how to achieve dual WeChat login on Huawei mobile phones. First of all, the EMUI system that comes with Huawei mobile phones provides a very convenient function - dual application opening. Through the application dual opening function, users can simultaneously

PHP Programming Guide: Methods to Implement Fibonacci Sequence PHP Programming Guide: Methods to Implement Fibonacci Sequence Mar 20, 2024 pm 04:54 PM

The programming language PHP is a powerful tool for web development, capable of supporting a variety of different programming logics and algorithms. Among them, implementing the Fibonacci sequence is a common and classic programming problem. In this article, we will introduce how to use the PHP programming language to implement the Fibonacci sequence, and attach specific code examples. The Fibonacci sequence is a mathematical sequence defined as follows: the first and second elements of the sequence are 1, and starting from the third element, the value of each element is equal to the sum of the previous two elements. The first few elements of the sequence

How to implement the WeChat clone function on Huawei mobile phones How to implement the WeChat clone function on Huawei mobile phones Mar 24, 2024 pm 06:03 PM

How to implement the WeChat clone function on Huawei mobile phones With the popularity of social software and people's increasing emphasis on privacy and security, the WeChat clone function has gradually become the focus of people's attention. The WeChat clone function can help users log in to multiple WeChat accounts on the same mobile phone at the same time, making it easier to manage and use. It is not difficult to implement the WeChat clone function on Huawei mobile phones. You only need to follow the following steps. Step 1: Make sure that the mobile phone system version and WeChat version meet the requirements. First, make sure that your Huawei mobile phone system version has been updated to the latest version, as well as the WeChat App.

Analysis of the meaning and usage of += operator in C language Analysis of the meaning and usage of += operator in C language Apr 03, 2024 pm 02:27 PM

The += operator is used to add the value of the left operand to the value of the right operand and assign the result to the left operand. It is suitable for numeric types and the left operand must be writable.

How to implement exact division operation in Golang How to implement exact division operation in Golang Feb 20, 2024 pm 10:51 PM

Implementing exact division operations in Golang is a common need, especially in scenarios involving financial calculations or other scenarios that require high-precision calculations. Golang's built-in division operator "/" is calculated for floating point numbers, and sometimes there is a problem of precision loss. In order to solve this problem, we can use third-party libraries or custom functions to implement exact division operations. A common approach is to use the Rat type from the math/big package, which provides a representation of fractions and can be used to implement exact division operations.

Master how Golang enables game development possibilities Master how Golang enables game development possibilities Mar 16, 2024 pm 12:57 PM

In today's software development field, Golang (Go language), as an efficient, concise and highly concurrency programming language, is increasingly favored by developers. Its rich standard library and efficient concurrency features make it a high-profile choice in the field of game development. This article will explore how to use Golang for game development and demonstrate its powerful possibilities through specific code examples. 1. Golang’s advantages in game development. As a statically typed language, Golang is used in building large-scale game systems.

PHP Game Requirements Implementation Guide PHP Game Requirements Implementation Guide Mar 11, 2024 am 08:45 AM

PHP Game Requirements Implementation Guide With the popularity and development of the Internet, the web game market is becoming more and more popular. Many developers hope to use the PHP language to develop their own web games, and implementing game requirements is a key step. This article will introduce how to use PHP language to implement common game requirements and provide specific code examples. 1. Create game characters In web games, game characters are a very important element. We need to define the attributes of the game character, such as name, level, experience value, etc., and provide methods to operate these

Mind map of Python syntax: in-depth understanding of code structure Mind map of Python syntax: in-depth understanding of code structure Feb 21, 2024 am 09:00 AM

Python is widely used in a wide range of fields with its simple and easy-to-read syntax. It is crucial to master the basic structure of Python syntax, both to improve programming efficiency and to gain a deep understanding of how the code works. To this end, this article provides a comprehensive mind map detailing various aspects of Python syntax. Variables and Data Types Variables are containers used to store data in Python. The mind map shows common Python data types, including integers, floating point numbers, strings, Boolean values, and lists. Each data type has its own characteristics and operation methods. Operators Operators are used to perform various operations on data types. The mind map covers the different operator types in Python, such as arithmetic operators, ratio

See all articles