“特权”方法调用成员方法问题

发布于 2024-11-14 17:11:34 字数 1046 浏览 2 评论 0原文

考虑以下代码:

function Dog()
{
    this.foo = function() {};

    this.walk = function()
    {
        if(canWalk())
        {
            alert('walking');
            return;
        }

        alert('I have no legs!');
    }

    canWalk = function()
    {
        this.foo();
        return false;
    }
}

var instance = new Dog();
instance.walk();

该代码中的“特权”canWalk() 方法存在一个错误,假设 this 指针指向 Dog 的实例代码>.它实际上似乎指向全局对象,这让我感到困惑!我读过,由于闭包,我可以在构造函数的范围内获取对 this 的引用,然后在我的“特权”方法中使用该引用,但这似乎是一种黑客行为。

我只是勉强掌握 this 指针在各种上下文中的行为。据我所知,“附加”到对象的方法将接收指向附加对象的 this 。例如,foo.doStuff() 将有一个 this 指向 foo 实例。

令人不安的是,虽然我认为我很聪明并在我的对象上创建了“特权”方法,但看来我实际上正在将函数转储到全局范围内!也许有一个名为 init() 的全局方法(很有可能)来自另一个库或文件,而不是我自己创建的。如果我随后使用名为 init() 的“特权”方法定义了一个漂亮的小封装对象,我将替换另一个全局 init() 方法。

我的问题是,创建范围仅限于它们所属对象的“特权”方法(以及与此相关的字段)的最佳实践是什么?我的示例对象的其他方法可以提供私有或特权方法,同时也具有适当的范围。我不是在寻找满足要求的晦涩解决方案,而是寻找最佳实践。

Consider the following code:

function Dog()
{
    this.foo = function() {};

    this.walk = function()
    {
        if(canWalk())
        {
            alert('walking');
            return;
        }

        alert('I have no legs!');
    }

    canWalk = function()
    {
        this.foo();
        return false;
    }
}

var instance = new Dog();
instance.walk();

There is a bug in that code with the "privileged" canWalk() method assuming the this pointer points to the instance of Dog. It actually appears to be pointing to the global object which is confusing me! I've read that due to closures I can grab a reference to this in the scope of the constructor then use that reference in my "privileged" method but that seems like a hack.

I just barely grasp the behavior of the this pointer in various contexts. I understand that a method that is "attached" to an object will receive a this pointing to the attached object. For example, foo.doStuff() would have a this pointing to the foo instance.

What's troubling is that while I think I'm being clever and creating "privileged" methods on my OBJECT, it appears that I'm ACTUALLY dumping functions into global scope! Perhaps there was a global method called init() (quite possible) from another library or file not my own creation. If I then defined a nice little encapsulated object with a "privileged" method called init() I would be replacing the other global init() method.

My question is, what is the best practice for creating "privileged" methods (and fields for that matter) that are scoped to the object they are intended to belong to? What other approach to my sample object would provide private or privileged methods while also being properly scoped. I'm not looking for obscure solutions that meet the requirements but rather what the best practice is.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

雨轻弹 2024-11-21 17:11:34

不要使用这个。将 var self = this; 放在 Dog 函数的顶部并使用 self。这样您将始终拥有对狗的“安全”引用。

在你的例子中,this应该指向Dog,除非我也遗漏了一些东西。

至于您的特权方法,您忘记定义变量。添加 var canWalk;

还有另一种方式:闭包。我举个例子:

function create_dog() {
    function canWalk() {
        return false;
    }
    function walk() {
        if (canWalk()) {
            alert("walking");
            return;
        }
        alert("I have no hands!");
    }
    return {
        "walk": walk // points to the function walk()
    }; // this the API of dog, like public functions (or properties)
}
var dog = create_dog();
dog.walk();

现在你不需要 thisnew。另外,您可以这样做:

function create_dog() {
    function canWalk() {
        return false;
    }
    function walk() {
        if (canWalk()) {
            alert("walking");
            return;
        }
        alert("I have no hands!");
    }
    var dog = {
        "walk": walk
    };
    return dog;
}
var dog = create_dog();
dog.walk();

这样您就可以在权限函数中引用dog如果您不打算使用原型设计,我建议您使用封闭方法。

顺便说一下。为避免混淆:

function my_func() {}

var my_func = function () {};

是等效的。如果两个函数之间有循环引用并且想要强制使用前定义,则后者可能很有用。

Don't use this. Put var self = this; at the top of your Dog function and use self. That way you will always have a 'safe' reference to the Dog.

In your example this should point to the Dog though unless I'm missing something as well.

As for your privileged method, you forgot to define the variable. Add var canWalk;

There is another way: closures. I will give an example:

function create_dog() {
    function canWalk() {
        return false;
    }
    function walk() {
        if (canWalk()) {
            alert("walking");
            return;
        }
        alert("I have no hands!");
    }
    return {
        "walk": walk // points to the function walk()
    }; // this the API of dog, like public functions (or properties)
}
var dog = create_dog();
dog.walk();

Now you don't need this or new. Additionally you could do this:

function create_dog() {
    function canWalk() {
        return false;
    }
    function walk() {
        if (canWalk()) {
            alert("walking");
            return;
        }
        alert("I have no hands!");
    }
    var dog = {
        "walk": walk
    };
    return dog;
}
var dog = create_dog();
dog.walk();

So you can have references to the dog in your priveledges functions. I would advise the closure approach if you're not going to be using prototyping.

By the way. To avoid confusion:

function my_func() {}

and

var my_func = function () {};

Are equivalent. The latter can be useful if you have a circular reference between two functions and you want to enforce define-before-use.

会傲 2024-11-21 17:11:34

首先,您需要在 canWalk 前面添加一个 var。这样,canWalk 函数就被限制在 dog() 的范围内,而不是成为隐式全局函数。

this 指向函数的“所有者”。当使用 new 运算符时,该函数会创建自己的作用域。因此,在 dog() 体内,this 指的是狗实例对象。在您的 walk 函数中,this 也指的是狗实例,因为您将 walk 函数设置为 dog 的实例 (this.walk = function () { ... })。然而,在canWalk中,没有所有者,因此this指向全局对象window

我意识到我的解释可能会令人困惑,所以这是我的解释的代码注释版本:

var obj = {
    'f': function () {
        // this === obj, because obj "owns" this function
        // In other words, this function is callable by obj.f()
    },
    'o': {
         'f': function () {
             // this === obj.o, because obj.o "owns" this function
             // In other words, this function is callable by obj.o.f()
         }
    }
};

// The new operator essentially sets "this" within the 
// function to an empty object and returns that object
var instance = new Dog();

function Dog() {
    // this === instance, because of the "new" operator

    // For demonstration
    var self = this;

    this.walk = function () {
        // this === instance === self, because self/instance "owns" this function
        // In other words, this function is callable by self.walk()
    };

    var canWalk = function () {
        // What's the owner of this object? Nothing,
        // so it defaults to the global object, window
        // this === window

        // Instead, we can access the Dog instance by
        // using the "self" variable we set earlier.
        // self === instance
    };
}

希望能够澄清问题。

First, you need a var in front of your canWalk. That way, the canWalk function is confined to the scope of dog(), rather than being an implicit global.

this points to the "owner" of the function. When using the new operator, the function creates its own scope. So, within the body of dog(), this refers to the dog instance object. Inside your walk function, this also refers to the dog instance, because you're setting the walk function to an instance of dog (this.walk = function () { ... }). However, in canWalk, there is no owner, so this points to the global object, window.

I realize that my explanation might be confusing, so here's the code annotation version of my explanation:

var obj = {
    'f': function () {
        // this === obj, because obj "owns" this function
        // In other words, this function is callable by obj.f()
    },
    'o': {
         'f': function () {
             // this === obj.o, because obj.o "owns" this function
             // In other words, this function is callable by obj.o.f()
         }
    }
};

// The new operator essentially sets "this" within the 
// function to an empty object and returns that object
var instance = new Dog();

function Dog() {
    // this === instance, because of the "new" operator

    // For demonstration
    var self = this;

    this.walk = function () {
        // this === instance === self, because self/instance "owns" this function
        // In other words, this function is callable by self.walk()
    };

    var canWalk = function () {
        // What's the owner of this object? Nothing,
        // so it defaults to the global object, window
        // this === window

        // Instead, we can access the Dog instance by
        // using the "self" variable we set earlier.
        // self === instance
    };
}

Hope that clears things up.

茶花眉 2024-11-21 17:11:34

正如您所了解的,像这样直接调用 canWalk 意味着“this”关键字被设置为该函数调用的全局对象。

如果您想在当前狗的上下文中运行调用,您可以显式执行以下操作:

canWalk.call(this)

As you've gathered, calling canWalk straight up like that means that the 'this' keyword is set to the global object for that function call.

If you want to run the call under the context of the current dog you can explicitly do so like this:

canWalk.call(this)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文