范围问题和JSON" class"方法

时间:2014-04-24 18:11:56

标签: javascript json object scope

对于我遇到的这个问题,我真的找不到一个清晰简洁的答案 - 我甚至不确定如何说出来。但是我正在使用Javascript(一个“类”,如果你愿意的话)构建一个我可以重用的对象。我正在使用JSON方法来处理对象,因为这是我目前熟悉的唯一方法(我知道其他方法,我只是无法坐下来尝试它们)。 / p>

所以,这是我正在做的一个例子:

var Thing = {
    'property':{
        'one':5,
        'two':3
    },
    'action':(function(arg1, arg2){
        alert(arg1 + ' ' + arg2);
        return this.property.one + this.property.two;
    });
}

var t = Thing;
alert(t.action('x', 'y'));

正如你所看到的,我有了我的对象,并且它有一些嵌套属性。还有一个函数,它应该能够操纵所述属性。

我遇到的问题是范围。我想找到一种方法来引用函数中的对象属性,而不是假定属性属于该函数,因为它们没有。我在过去做过,我刚刚将“this”作为参数传递给函数,一切正常,但我愿意打赌这不是好习惯。另外,正如您所看到的,此函数无论如何都已经有了一些参数。运行此代码会出现错误:“Uncaught TypeError:无法读取未定义的属性'one'。

我想保留构建此对象的方法 - 这是工作的东西,对象已经非常大了;但是我正在寻找的是“回到树上”以获得这些属性。

5 个答案:

答案 0 :(得分:2)

您正在此处直接初始化对象。您正在使用的JSON称为object literal。顾名思义,它实际上是字面上的定义对象。

现在让我们来解决你的问题。

当您声明具有this.property.one的函数时,this关键字将在通话时解析。它通常是浏览器上的窗口对象。 Read on more this。所以永远不会指向你的Thing。您可以做的是为类定义一个函数并将函数添加到其原型中。这是在js中实现oop的经典方式。

function Thing(){
    this.property = {one: 5, two: 3}
}

Thing.prototype.action = function(arg1, arg2){
    alert(arg1 + ' ' + arg2);
    return this.property.one + this.property.two;
}

答案 1 :(得分:1)

这有效:

var Thing = {
    'property':{
        'one':5,
        'two':3
    },
    'action':(function(arg1, arg2){
        alert(arg1 + ' ' + arg2);
        return this.property.one + this.property.two;
    }) // here don't put a ';'
}

var t = Thing;
alert(t.action('x', 'y'));

答案 2 :(得分:0)

你应该定义一个函数。

var Thing = function(){
    this.property = {"one":5, "two":3};
    this.action = function(arg1, arg2){/*....*/}
}

var y = new Thing();
alert(y.action("x","y"));

这就是我写课的方式。

正如另一个答案所说,看起来你有;不应该

答案 3 :(得分:0)

我有两个答案,一个使用您当前的JSON模型,另一个使用更多Javascript方式。

:一种。

如此定义 Thing

var Thing = {
    'property':{
        'one':5,
        'two':3
    },
    'action':(function(arg1, arg2){
        alert(arg1 + ' ' + arg2);
        return this.property.one + this.property.two;
    })
}

您创建了一个文字,这意味着每次执行

等代码
var t = Thing;

您通过引用传递,不要在内存中创建新对象。因此,使用多个引用Thing的变量会产生问题。

此外,您的问题还会形成这样一个事实:关键字 this 是在运行时找到的,除非由 bind 命令指定,否则通常会引用浏览器窗口。请记住,它必须始终是一个对象。文字的本质是这样的,它不会以外行的方式改变这个变量。

<强>乙

现在以更好的方式解决这个问题。可以像其他任何函数一样创建可实例化的对象或类。但是,它们由关键字 new 实例化。为了使用它们自己的引用, this 关键字表示当前范围中派生程度最大的可实例化类。因此,你的例子写得更好

var Thing = function(){
    this.property = {};
    this.property.one = 5;
    this.property.two = 3;

    this.action = function Action(arg1, arg2){
        alert(arg1 + ' ' + arg2);
        return this.property.one + this.property.two;
    }
}

var t = new Thing();
alert(t.action('x', 'y'));

我希望有所帮助。

<强>此外

你说

  

我正在寻找的是“回到树上”

虽然我不太清楚你的意思,但我推断如果我到目前为止所说的内容没有帮助,你的意思是你在物体内有物体。例如,假设您有一个也包含Schedule类的Student类。您可能希望从计划类中访问学生数据。虽然这个例子很糟糕,因为按设计,Schedule实例不需要访问Student数据,如果需要,它应该通过函数参数传递,你也可以解决这个问题。

function Student(age){
    this.age = age;
    this.schedule = new Schedule(this);
}

function Schedule(parent){
    this.getAge = function(){return parent.age;}
}

var s = new Student(16);
s.schedule.getAge();

您可以简单地将父对象传递给子对象的实例并完成,按照您的说法备份树。

答案 4 :(得分:0)

如果您需要一个生成不同对象的“类”,那么我认为您应该查看shiplu.mokadd.im的答案。但是,你可能需要一个模块,有点像单身:

var thing = (function() {
    var property = {
        one:5,
        two:3
    };

    function action(arg1, arg2){
        alert(arg1 + ' ' + arg2);
        return property.one + property.two;
    }

    return {
        action: action
    };
})();

alert(thing.action('x', 'y'));

这里发生了什么:使用所谓的IIFE - 立即调用的函数表达式。它在这里做什么它分配给thing var无论IIFE返回什么(immidiately) - 所以在这种情况下它返回一个具有action函数的对象。

为什么这有用?它在IIFE中创建了一个范围,它封装了你要做的任何事情thing。它还会创建“私有”函数和变量 - 您只需return所需的内容 - 例如。 var propertything之外不可见,您无法获得对thing.property的引用。

希望这有用!