简体   繁体   English

访问当前对象的简单方法

[英]Simple way to access current object

I'm trying to find a simple way to refer to the current instance of an object from the object methods itself (similar to this keyword in any decent language). 我试图找到一种简单的方法从对象方法本身引用一个对象的当前实例(类似于任何体面语言中的this关键字)。

I've tried many variations of "storing a pointer for itself" (like window.window.window do), but always something go wrong. 我尝试了很多“为自己存储指针”(如window.window.window ),但总会出错。 For example: 例如:

function ClassA() {
  var mySelf = this;

  this.myMethod = function() {
    console.log(mySelf); //Once you extend this class, mySelf will not be available
  }
}

function ClassB() {
  this.mySelf = this; //Ok, now you can extend this and mySelf will be there

  this.myMethod = function() {
    console.log(mySelf);//"mySelf is not defined" because it's a property now
    console.log(this.mySelf);//Value of 'this' and 'self' will vary
    console.log(RandomContainer.ClassBInstance.mySelf);//I can't use a defined path
  }
}

Since everything about OOP in JavaScript is hackish, I have to ask... 既然JavaScript中的OOP一切都是hackish,我不得不问......

Is there any magic to refer to the current object that a method is being called from? 是否有任何魔法可以引用当前对象来调用方法?


EDIT 编辑

A lot of possible solutions in the comments, thanks guys! 在评论中有很多可能的解决方案,谢谢你们! But I still need to improve my question. 但我仍然需要改进我的问题。 So I'll add some piece of code with my failed attempts, and then try out the proposed solutions... 因此,我会在失败的尝试中添加一些代码,然后尝试提出的解决方案......

function BaseController()
{
    var myPriv = 42;
    return {
        getAnswer: function() {
            return myPriv;
        }
    };
}

function SomeController()
{
    return {
        showAnswer: function()
        {
            var answer;
            answer = myPriv; //I need some way to access this
            answer = getAnswer(); //Also a way to refer to my own methods 
            //(I don't even find a way to call 'showAnswer' from this context)

            console.log('The answer is ' + answer);
        }
    };
}

//That's how I was extending my classes so far...
var someControllerInstance = jQuery.extend(
    new BaseController(),
    new SomeController()
    );

someControllerInstance.getAnswer(); //Works!
someControllerInstance.showAnswer(); //Reference errors...

take time to learn the idiosyncrasies of js, be warned though, it's like marmite. 花时间学习js的特性,但要注意,它就像是marmite。

If you'll allow me to be blunt for a moment, you are approaching JavaScript with the wrong frame of mind. 如果你让我迟钝,你就会以错误的心态接近JavaScript。 It is not designed for classical inheritance, nor for protected properties or methods, and there is no benefit in bending it that way. 它不是为经典继承而设计的,也不是为受保护的属性或方法设计的,并且以这种方式弯曲它没有任何好处。 To be honest I find towering stacks of inheritance a pain to read and navigate, unless you have a singing-all-dancing IDE that may take a week to load. 说实话,我发现高耸的遗产堆栈是一种阅读和导航的痛苦,除非你有一个可以花费一周时间加载的全能舞蹈IDE。 The closer to flat and open you can achieve — whilst still keeping things flexible — the better you are at coding, and the more other coders that may take over your work will thank you. 你可以实现更接近平坦和开放 - 同时保持灵活性 - 你编码的效果越好,可能接管你工作的其他编码人员也会感谢你。 (obviously that is opinion) (显然那是意见)

For more information on prototype inheritance read the following informative post: 有关原型继承的更多信息,请阅读以下信息性帖子:

http://davidwalsh.name/javascript-objects-deconstruction http://davidwalsh.name/javascript-objects-deconstruction

Below is an example of prototype inheritance, it should be noted that Object.create and isPrototypeOf are relatively new and do not exist for older JavaScript interpreters. 下面是原型继承的一个例子,应该注意的是Object.createisPrototypeOf是相对较新的,并且对于旧的JavaScript解释器不存在。 Approximate polyfills can be used in most cases however. 然而,在大多数情况下可以使用近似的填充物。

Put simply JavaScript becomes much more powerful when you think in terms of objects borrowing methods from wherever they may be found, and not instances rigidly inheriting from slightly less specific instances; 简单地说,当您从对象借用方法的角度考虑时,JavaScript变得更加强大,而不是从稍微不那么具体的实例中严格继承的实例; or worse, constructors that keep rebuilding the same functions again and again. 或者更糟糕的是,一次又一次地重建相同功能的构造函数。

The following is just an example, and across my 16 years of coding ECMAScript I have barely ever needed anything that approaches classical inheritance, nor have I needed objects that heavily inherit on the prototype chain either. 以下只是一个例子,在我编写ECMAScript的16年中,我几乎不需要任何接近经典继承的东西,也不需要在原型链上大量继承的对象。 More often than not my js is basically just a number of newly created objects, properly name-spaced, that borrow methods from fixed pools of functions; 通常情况下,我的js基本上只是一些新创建的对象,正确的名称间隔,从固定的函数池中借用方法; any type detections are duck-typed, and I'm careful to keep everything as local as possible. 任何类型的检测都是鸭子型的,我小心翼翼地保持一切尽可能本地化。

Anyway, here's something I don't often use: 无论如何,这是我经常使用的东西:

var Make = function(construct){
  return Object.create(construct);
};

var Extend = function(proto, props){
  var instance = Object.create(proto);
  for ( var i in props ) { instance[i] = props[i]; }
  instance.super = proto; // this should never be needed really
  return instance;
};

var Animal = {
  keepBreathing: function(){
    console.log('animal', this);
  }
};

var Monkey = Extend(Animal, {
  climbTree: function(){
    console.log('monkey', this);
    console.log('monkey', this.super);
  }
});

var KeyserSoze = Make(Monkey);
    KeyserSoze.keepBreathing(); /// animal, instance of KeyserSoze
    KeyserSoze.climbTree();     /// monkey, instance of KeyserSoze

console.log('an instance of monkey', KeyserSoze);
console.log('has animal as proto', Animal.isPrototypeOf(KeyserSoze)); // true
console.log('has monkey as proto', Monkey.isPrototypeOf(KeyserSoze)); // true

Whilst the above does follow a kind of classical layout ie Monkey inherits methods from Animal, you could approach things in a different way. 虽然上面的确遵循一种经典的布局,即Monkey继承了Animal的方法,但你可以用不同的方式处理事物。 The following is more open to dynamic changes, in the fact you could switch out the behaviours object for another interface entirely. 以下内容对动态更改更加开放,事实上您可以完全切换出另一个界面的行为对象。 Again, this is just an illustration that you don't have to construct things in a fixed way. 同样,这只是一个例子,您不必以固定的方式构建事物。

Something I'm more likely to use: 我更有可能使用的东西:

var AnimalBehaviours = {
  keepBreathing: function(){
    (this.breathCount === undefined) && (this.breathCount = 0);
    this.breathCount++;
  }
};

var ApeLikeDescendant = (function( behaviours ){
  return {
    create: function( config ){
      return Object.create(this).prep(config);
    },
    prep: function( config ){
      /// do your instance specific set up here
      return this;
    },
    climbTree: function(){
      console.log('ape-like', this);
    },
    keepBreathing: function(){
      return behaviours.keepBreathing.apply(this, arguments);
    },
    switchBehaviours: function(newBehaviours){
      behaviours = newBehaviours;
    }
  };
})(AnimalBehaviours);

var DouglasAdams = ApeLikeDescendant.create({});

You could adapt the above to behave more in a manner similar to mixins ie you'd take the behaviours, step through them and merge them to the ApeLike object... it's really quite open to whatever your goal is. 你可以调整上面的行为,以类似于mixin的方式运行,即你采取行为,逐步完成它们并将它们合并到ApeLike对象......无论你的目标是什么,它都非常开放。

Something that I use regularly: 我经常使用的东西:

var ElementEdgeCases = {
  makeWorkOnNetscape47: function(){
    this.target; /// Intentionally left almost blank.
  }
};

var ElementFinagler = (function(){
  var finagle = {
    target: null,
    prep: function( element ){
      this.target = element;
      return this;
    },
    addClass: function(){
      var c = this.target.getAttribute('className'); /// and so on ...
      return this;
    },
    elaborate: function( mixin ){
      for ( var i in mixin ) {
        if ( mixin.hasOwnProperty(i) ) {
          this[i] = mixin[i];
        }
      }
      return this;
    }
  };
  return function( element ){
    return Object.create(finagle).prep(element);
  };
})();

var elm = document.getElementsByTagName('body')[0];

ElementFinagler(elm)
  .elaborate(ElementEdgeCases) // extend the object if we need
  .addClass('hello world')
;

The main thing to keep in mind with JavaScript is that no function is owned by anything, not really. 使用JavaScript时要记住的主要事情是没有任何函数属于任何东西,不是真的。 Every time you execute a function, the function's context is implied by the way you call that function — the context is computed at call time. 每次执行函数时,函数的上下文都会被调用该函数的方式所暗示 - 上下文是在调用时计算的。 This allows a great deal of flexibility, and whilst you mention that calling function.apply(context, args) or function.call(context, arg, arg, ...) every time is cumbersome; 这允许很大的灵活性,同时你提到调用function.apply(context, args)function.call(context, arg, arg, ...)每次都很麻烦; it is very easy to codify your own system for hiding that repetition away. 编写自己的系统来隐藏重复是非常容易的。

Oh, and before I forget, one other thing to take away from the code above is that there is no duplication of function creation. 哦,在我忘记之前,从上面的代码中拿走的另一件事是没有重复的函数创建。 Every instance shares the same functions in memory. 每个实例在内存中共享相同的功能。 This is an important thing to bear in mind if you are planning to create large scale applications, as you can quickly eat up memory with multiple instances of functions. 如果您计划创建大规模应用程序,请记住这一点很重要,因为您可以使用多个函数实例快速占用内存。

So just to recap: 所以回顾一下:

  1. Forget inheritance, it's rarely required for many js projects. 忘记继承,许多js项目很少需要它。
  2. Create flexible objects that can be extended when required. 创建可在需要时扩展的灵活对象。
  3. Borrow methods when you need them from other objects, using apply or call to change context. 当您需要从其他对象使用它们时,使用applycall来更改上下文。
  4. Keep your code open, there is no need for private; 保持代码开放,不需要私密; open is more extensible. open更具可扩展性。
  5. Private no, but having properties not enumerable is a different story, see defineProperty . 私有,但具有不可枚举的属性是一个不同的故事,请参阅defineProperty
  6. Make sure you do not duplicate functions — unless you have to — instead create them once and reference. 确保你没有复制函数 - 除非你必须 - 而是创建它们一次并引用。

this referrers to the dom node that an event originated from, or the javascript object it is a child of. this引用了事件源自的dom节点,或者它是javascript对象的子节点。 In that order. 以该顺序。

this.parentNode referrers the dom node's parent (Not sure if it works in object context). this.parentNode引用dom节点的父节点(不确定它是否在对象上下文中工作)。

When I write javascript I'll usually try to leverage the html's dom itself, nesting things mindful of how the JS needs to reference them. 当我编写javascript时,我通常会尝试利用html的dom本身,嵌套注意JS需要如何引用它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM