Javascript 如何从另一个对象中的函数中引用顶级对象

Javascript 如何从另一个对象中的函数中引用顶级对象,javascript,ecmascript-6,Javascript,Ecmascript 6,我有一个颜色对象作为字符串-这些颜色的子集包含另一个名为渐变的对象,它是函数对象。在这些函数中-如何引用渐变的同级颜色 test0是{…cyan400,} test1是{} 函数中的此未定义 在每种情况下,这个的值背后的原因我们能得到解释吗 { ... cyan400: "#a6fcff", cyan200: "#d9feff", test0: this, gradients: { test1: this, g

我有一个颜色对象作为字符串-这些颜色的子集包含另一个名为
渐变的对象,它是函数对象。在这些函数中-如何引用
渐变的同级颜色

  • test0
    {…cyan400,}
  • test1
    {}
  • 函数中的此
    未定义
在每种情况下,
这个
的值背后的原因我们能得到解释吗


{
    ...
    cyan400: "#a6fcff",
    cyan200: "#d9feff",

    test0: this,

    gradients: {

        test1: this,

        g1: (angle = "0deg") => oneLineTrim`
            linear-gradient(
                ${angle},
                ${this.magenta600} 0%,
                ${this.purple800} 50%,
                ${this.indigo800} 100%
            )
        `,
        ...
    }
}

简而言之,当对象嵌套在其他对象中时,Javascript中就没有“父”对象。该语言无法帮助您获得对父级的引用。您必须自己直接按名称引用顶级对象,或者将对顶级对象的引用作为属性手动放置在较低级别对象中

当我定义对象并将其分配给变量
data
并运行代码并查看
data.test0
data.gradients.test1
的值以及
data.gradients.g1()函数内部的
this
的值时,它们对我来说都有完全相同的值,这是定义对象的范围内
this
的词法值。这就是它的工作原理
指的是声明对象的词法范围,而不是对象本身。在非fat arrow方法(使用常规函数声明的方法)中,
这将由方法的调用方式决定

有些人对此感到困惑,因为当你调用一个常规方法(没有用粗箭头定义)时,该方法中的
this
的值通常是该方法所属的对象。这是因为调用方法时如何设置
This
的值。您可以看到在这个答案的常规方法调用中设置
this
值的六种方式:

Javascript语言中没有自动引用“父”对象的机制。Javascript中的对象实际上并不“包含”在彼此之间。当您执行这样的嵌套定义时,内部对象将自行创建并自行进行垃圾收集,而外部对象仅包含对它们的引用。程序中其他地方的其他变量很可能包含对嵌套对象的相同引用,这些嵌套对象包含在其他对象的属性中。因此,Javascript中没有实际的“父”对象

那么,让我们来看一些与您发布的内容相关的可运行代码:

this.greeting = "hello";

let data = {
    cyan400: "#a6fcff",
    cyan200: "#d9feff",
    test0: this,
    gradients: {
        test1: this,
        g1: (angle = "0deg") => {
            console.log(this);
        }
    }
}

console.log(data.test0);
console.log(data.gradients.test1);
data.gradients.g1();
当我在node.js中运行此命令时,最后三条语句都显示完全相同的输出:

{ greeting: "hello" }
因为此
的所有三个值都相同,这与预期相同

如果我这样做,请将常规方法添加到
gradients
对象并调用它:

this.greeting = "hello";

let data = {
    cyan400: "#a6fcff",
    cyan200: "#d9feff",
    test0: this,
    gradients: {
        test1: this,
        g1: (angle = "0deg") => {
            console.log(this);
        },
        g2: function() {
            console.log(this);
        }
    }
}

data.gradients.g2();
然后,g2中该
的值将成为渐变对象。这是因为它是用
obj.method()
语法调用的,并且它被声明为一个常规函数(不是胖箭头函数),因此
obj.method()
this
的值被设置为
obj
,在这种情况下,它是
渐变
对象


如果您试图引用父对象中的属性,则无法使用
this
或任何其他机制在Javascript中自动引用该属性。您必须在
渐变中放置对顶层对象的引用,如下所示:

let data = {
    cyan400: "#a6fcff",
    cyan200: "#d9feff",
    test0: this,
    gradients: {
        test1: this,
        g1: (angle = "0deg") => {
            // use property manually set on this object
            // to get to the object that has the colors
            console.log(this.colors.cyan400);
        }
    }
}

// set reference to parent object that contains the colors
// can't be done inside the static declaration, has to be done afterwards
data.gradients.colors = data;
或者,引用对象本身的顶级名称并以这种方式获得颜色:

let data = {
    cyan400: "#a6fcff",
    cyan200: "#d9feff",
    test0: this,
    gradients: {
        test1: this,
        g1: (angle = "0deg") => {
            // reference top level object directly
            console.log(data.cyan400);
        }
    }
}

简而言之,当对象嵌套在其他对象中时,Javascript中就没有“父”对象。该语言无法帮助您获得对父级的引用。您必须自己直接按名称引用顶级对象,或者将对顶级对象的引用作为属性手动放置在较低级别对象中

当我定义对象并将其分配给变量
data
并运行代码并查看
data.test0
data.gradients.test1
的值以及
data.gradients.g1()函数内部的
this
的值时,它们对我来说都有完全相同的值,这是定义对象的范围内
this
的词法值。这就是它的工作原理
指的是声明对象的词法范围,而不是对象本身。在非fat arrow方法(使用常规函数声明的方法)中,
这将由方法的调用方式决定

有些人对此感到困惑,因为当你调用一个常规方法(没有用粗箭头定义)时,该方法中的
this
的值通常是该方法所属的对象。这是因为调用方法时如何设置
This
的值。您可以看到在这个答案的常规方法调用中设置
this
值的六种方式:

Javascript语言中没有自动引用“父”对象的机制。Javascript中的对象实际上并不“包含”在彼此之间。当您执行这样的嵌套定义时,内部对象将自行创建并自行进行垃圾收集,而外部对象仅包含对它们的引用。程序中其他地方的其他变量很可能包含对嵌套对象的相同引用,这些嵌套对象包含在其他对象的属性中。因此,Javascript中没有实际的“父”对象

那么,让我们来看一些与您发布的内容相关的可运行代码:

this.greeting = "hello";

let data = {
    cyan400: "#a6fcff",
    cyan200: "#d9feff",
    test0: this,
    gradients: {
        test1: this,
        g1: (angle = "0deg") => {
            console.log(this);
        }
    }
}

console.log(data.test0);
console.log(data.gradients.test1);
data.gradients.g1();
当我在node.js中运行此命令时,最后三条语句都显示完全相同的输出: