什么是名称冲突?ES6符号如何避免属性之间的名称冲突?

时间:2019-06-19 00:46:16

标签: javascript ecmascript-6 es6-symbol

我试图更好地理解ES6中的符号,并且我已经阅读了以下答案:

https://stackoverflow.com/a/22280202/5591717

  

它们现在被称为唯一符号,它们的唯一用途是避免属性之间的名称冲突。

名称冲突仅表示一个名称遮盖另一个名称吗?还是也意味着错误,无法重新声明某些内容?

一个例子:

let color = Symbol('this is a color')

let apple = {
  [color]: 'red'
}

console.log(apple[color]) //red
console.log(apple.color) //undefined 

apple[color] = 'black'

console.log(apple[color]) //black
console.log(apple.color) //undefined

apple.color = 'white'

console.log(apple[color]) //black
console.log(apple.color) //white

即使通过符号访问属性,似乎属性也会被遮盖。

并且它们还允许与符号名称相同名称的点表示法属性以不同的值共存。这是避免名称冲突的意思吗?

1 个答案:

答案 0 :(得分:4)

这不是阴影:

  

在计算机编程中,当在某个范围(决策块,方法或内部类)中声明的变量与在外部范围中声明的变量具有相同的名称时,将发生变量阴影。据说这个外部变量被遮盖了...

例如

import cv2

class ExtractImageWidget(object):
    def __init__(self):
        self.original_image = cv2.imread('1.jpg')

        # Resize image, remove if you want raw image size
        self.original_image = cv2.resize(self.original_image, (640, 556))
        self.clone = self.original_image.copy()

        cv2.namedWindow('image')
        cv2.setMouseCallback('image', self.extract_coordinates)

        # Bounding box reference points and boolean if we are extracting coordinates
        self.image_coordinates = []
        self.extract = False

    def extract_coordinates(self, event, x, y, flags, parameters):
        # Record starting (x,y) coordinates on left mouse button click
        if event == cv2.EVENT_LBUTTONDOWN:
            self.image_coordinates = [(x,y)]
            self.extract = True

        # Record ending (x,y) coordintes on left mouse bottom release
        elif event == cv2.EVENT_LBUTTONUP:
            self.image_coordinates.append((x,y))
            self.extract = False
            print('top left: {}, bottom right: {}'.format(self.image_coordinates[0], self.image_coordinates[1]))

            # Draw rectangle around ROI
            cv2.rectangle(self.clone, self.image_coordinates[0], self.image_coordinates[1], (0,255,0), 2)
            cv2.imshow("image", self.clone) 

        # Clear drawing boxes on right mouse button click
        elif event == cv2.EVENT_RBUTTONDOWN:
            self.clone = self.original_image.copy()

    def show_image(self):
        return self.clone

if __name__ == '__main__':
    extract_image_widget = ExtractImageWidget()
    while True:
        cv2.imshow('image', extract_image_widget.show_image())
        key = cv2.waitKey(1)

        # Close program with keyboard 'q'
        if key == ord('q'):
            cv2.destroyAllWindows()
            exit(1)

存储符号的变量名对任何东西都没有影响(这很好-代码 execution 不应取决于所使用的变量名)。您可以将其命名为const foo = 'foo'; (() => { // entirely separate variable which shadows outer variable with same name const foo = 'foo2'; })();而不是mySymbol,并且引擎将具有完全相同的输出:

color

当代码的完全独立的部分需要在对象上存储数据时,可以避免名称冲突。代码的不同部分可能不会互相了解,但是他们想确保一个人使用的属性与另一个人不同。这可以通过每个部分使用其自己的符号来完成,这使得两个代码部分不可能意外使用相同的属性名称,从而导致错误。例如:

let mySymbol = Symbol('this is a mySymbol')

let apple = {
  [mySymbol]: 'red'
}

console.log(apple[mySymbol]) //red
console.log(apple.color) //undefined 

apple[mySymbol] = 'black'

console.log(apple[mySymbol]) //black
console.log(apple.color) //undefined

apple.color = 'white'

console.log(apple[mySymbol]) //black
console.log(apple.color) //white

如果一个模块改用属性名// module1.js const module1 = (() => { const module1Sym = Symbol(); return (obj) => { // put some data on obj which can be retrieved by this module later obj[module1Sym] = 'module 1 data'; }; })(); // module2.js const module2 = (() => { const module2Sym = Symbol(); return (obj) => { // put some data on obj which can be retrieved by this module later obj[module2Sym] = 'module 2 data'; }; })(); const obj = {}; module1(obj); module2(obj);,则可能会出现问题-如果某个自称为module1的其他模块试图将数据存储在对象上怎么办?然后,事情就会崩溃:

module1data

以上是名称冲突的示例。两个模块意外使用了相同的属性名称。