如何在JavaScript中获取外部的“this”引用?

时间:2022-02-04 16:54:00

So I have a class lets call it A. For this class I have written a few functions which I can call like this:

我有一个类叫a,这门课我写了一些函数我可以这样叫:

var a = new A();
a.getSomething();
a.putSomething();
a.delSomething();

And so on. Now I thought I'd organize it a bit So it wouldn't get too cluttered and would look like a bit more like this:

等等。现在我想我应该把它整理一下,这样它就不会太杂乱,看起来会更像这样:

a.something.get();
a.something.put();
a.something.del();

And this is how I tried to achieve this:

这就是我努力做到的:

A.prototype.something = {
  get: function(){...},
  put: function(){...},
  del: function(){...}
};

But these functions (get, put and del) still need to access the common objects/functions found in A, so I need a reference to A, but I don't know how this can be achieved.

但是这些函数(get、put和del)仍然需要访问在A中找到的公共对象/函数,所以我需要一个对A的引用,但是我不知道如何实现这一点。

One option I found goes like that:

我发现一个选项是这样的:

A.prototype.something = function(){
  var that = this;
  return {
    get: function(){...},
    ...
  };
}; 

And 'that' would be used in those (get, put and del) functions instead of 'this'. But this would mean I would have to call these functions in such way:

而“that”将用于那些(get、put和del)函数中,而不是“this”。但这意味着我必须这样称呼这些函数:

a.something().get();
...

Which doesn't seem very nice to me. So is there a way I could organize these things the way I originally planned?

这对我来说不太好。那么我是否有办法按照我最初的计划来组织这些事情呢?

3 个解决方案

#1


4  

So I have a class

我有课

Javascript doesn't have classes. It has prototype inheritance that can emulate classes to a limited extent, but that isn't worthwhile purely for the sake of emulating classes. Much better to make optimal use of built–in language features rather than trying to make javascript emulate some other language.

Javascript不上课。它具有原型继承,可以在有限的范围内模拟类,但是仅仅为了模拟类而这么做并不值得。与其试图让javascript模仿其他语言,不如优化使用内置语言特性。

So you have a constructor...

你有一个构造函数。

I have written a few functions which I can call like this:

我写了一些函数,我可以这样称呼:

var a = new A();
a.getSomething();
a.putSomething();
a.delSomething();

Presumably those methods are all on A.prototype.

假设这些方法都是基于原型的。

And so on. Now I thought I'd organize it a bit So it wouldn't get too cluttered and would look like a bit more like this:

等等。现在我想我应该把它整理一下,这样它就不会太杂乱,看起来会更像这样:

a.something.get();
a.something.put();
a.something.del();

That isn't less cluttered (to me). I guess there is some common thing that is done by something, and that its get, put, etc. methods want to operate on a not on something.

(对我来说)这一点也不奇怪。我猜有一些常见的事情是由某物完成的,它的get, put等方法想要对a而不是某物进行操作。

The value of this is set by the call, there is no other way to set its value other than with ES5 bind. So the method being called must have access to a somehow. Other answers show how to do that with a closure, but the consequence is that each instance must have its own something object and attached methods.

这个值是由调用设置的,除了使用ES5 bind外,没有其他方法可以设置它的值。所以被调用的方法必须能够以某种方式访问a。其他的答案显示了如何使用闭包来实现这一点,但是结果是每个实例必须有自己的object对象和附加的方法。

The following is similar, but gets rid of the closure and puts the methods on Something.prototype for a bit of efficiency:

下面的内容类似,但是去掉闭包并将方法放在某物上。样机的效率:

function A(name) {
    this.name = name;
    this.something = new Something(this);
}


function Something(that){
    this.that = that;
}

Something.prototype.get = function() {
    return this.that.name;
}
Something.prototype.put = function(prop, value) {
    this.that[prop] = value;
}

var a = new A('a');

alert(a.something.get());     // a
a.something.put('name', 'z');
alert(a.something.get());     // z

So you can have multiple somethings, each with different put, get, etc. methods. But the intervening something object is really just a device that uses more memory (probably a tiny amount) and requires an extra character. Simpler to keep the something methods on A.prototype and not have to type the extra dot (.).

你可以有多个东西,每个都有不同的put、get等方法。但是,插入的对象实际上只是一个使用更多内存(可能是少量)的设备,需要额外的字符。使某些方法保持在A上更简单。原型,而不必输入额外的点(.)。

#2


6  

You can't add this to the prototype, because the something member is not the same on all objects - internally, its methods must obtain a closure to the outer object, which is not possible to obtain at the time of execution.

您不能将其添加到原型中,因为在所有对象上的成员都不是相同的——在内部,它的方法必须获得对外部对象的闭包,这在执行时是不可能获得的。

You need to do it in the constructor:

你需要在构造函数中完成:

function A() {
    var that = this;
    this.something = { 
       get: function(){...}, 
       ... 
    };
}

#3


0  

function A() {
  this.something = this;
}
A.prototype = {
  get: function(){...},
  put: function(){...},
  del: function(){...}
};

therefore:

因此:

a.something.get();
a.something.put();
a.something.del();

#1


4  

So I have a class

我有课

Javascript doesn't have classes. It has prototype inheritance that can emulate classes to a limited extent, but that isn't worthwhile purely for the sake of emulating classes. Much better to make optimal use of built–in language features rather than trying to make javascript emulate some other language.

Javascript不上课。它具有原型继承,可以在有限的范围内模拟类,但是仅仅为了模拟类而这么做并不值得。与其试图让javascript模仿其他语言,不如优化使用内置语言特性。

So you have a constructor...

你有一个构造函数。

I have written a few functions which I can call like this:

我写了一些函数,我可以这样称呼:

var a = new A();
a.getSomething();
a.putSomething();
a.delSomething();

Presumably those methods are all on A.prototype.

假设这些方法都是基于原型的。

And so on. Now I thought I'd organize it a bit So it wouldn't get too cluttered and would look like a bit more like this:

等等。现在我想我应该把它整理一下,这样它就不会太杂乱,看起来会更像这样:

a.something.get();
a.something.put();
a.something.del();

That isn't less cluttered (to me). I guess there is some common thing that is done by something, and that its get, put, etc. methods want to operate on a not on something.

(对我来说)这一点也不奇怪。我猜有一些常见的事情是由某物完成的,它的get, put等方法想要对a而不是某物进行操作。

The value of this is set by the call, there is no other way to set its value other than with ES5 bind. So the method being called must have access to a somehow. Other answers show how to do that with a closure, but the consequence is that each instance must have its own something object and attached methods.

这个值是由调用设置的,除了使用ES5 bind外,没有其他方法可以设置它的值。所以被调用的方法必须能够以某种方式访问a。其他的答案显示了如何使用闭包来实现这一点,但是结果是每个实例必须有自己的object对象和附加的方法。

The following is similar, but gets rid of the closure and puts the methods on Something.prototype for a bit of efficiency:

下面的内容类似,但是去掉闭包并将方法放在某物上。样机的效率:

function A(name) {
    this.name = name;
    this.something = new Something(this);
}


function Something(that){
    this.that = that;
}

Something.prototype.get = function() {
    return this.that.name;
}
Something.prototype.put = function(prop, value) {
    this.that[prop] = value;
}

var a = new A('a');

alert(a.something.get());     // a
a.something.put('name', 'z');
alert(a.something.get());     // z

So you can have multiple somethings, each with different put, get, etc. methods. But the intervening something object is really just a device that uses more memory (probably a tiny amount) and requires an extra character. Simpler to keep the something methods on A.prototype and not have to type the extra dot (.).

你可以有多个东西,每个都有不同的put、get等方法。但是,插入的对象实际上只是一个使用更多内存(可能是少量)的设备,需要额外的字符。使某些方法保持在A上更简单。原型,而不必输入额外的点(.)。

#2


6  

You can't add this to the prototype, because the something member is not the same on all objects - internally, its methods must obtain a closure to the outer object, which is not possible to obtain at the time of execution.

您不能将其添加到原型中,因为在所有对象上的成员都不是相同的——在内部,它的方法必须获得对外部对象的闭包,这在执行时是不可能获得的。

You need to do it in the constructor:

你需要在构造函数中完成:

function A() {
    var that = this;
    this.something = { 
       get: function(){...}, 
       ... 
    };
}

#3


0  

function A() {
  this.something = this;
}
A.prototype = {
  get: function(){...},
  put: function(){...},
  del: function(){...}
};

therefore:

因此:

a.something.get();
a.something.put();
a.something.del();