Javascript 访问当前对象的简单方法

Javascript 访问当前对象的简单方法,javascript,Javascript,我试图找到一种简单的方法,从对象方法本身引用对象的当前实例(类似于任何体面的语言中的this关键字) 我尝试过许多“为自身存储指针”的变体(如window.window.windowdo),但总是出现一些问题。例如: function ClassA() { var mySelf = this; this.myMethod = function() { console.log(mySelf); //Once you extend this class, mySelf will n

我试图找到一种简单的方法,从对象方法本身引用对象的当前实例(类似于任何体面的语言中的
this
关键字)

我尝试过许多“为自身存储指针”的变体(如
window.window.window
do),但总是出现一些问题。例如:

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
  }
}

由于JavaScript中关于OOP的所有内容都很粗糙,我不得不问

调用方法的当前对象有什么魔力吗?


编辑 在评论中有很多可能的解决方案,谢谢大家! 但我仍然需要改进我的问题。因此,我将在失败的尝试中添加一些代码,然后尝试提出的解决方案

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...
花点时间学习js的特性,不过要注意,它就像marmite。 请允许我直截了当地说一下,您是以错误的心态对待JavaScript的。它不是为经典继承而设计的,也不是为受保护的属性或方法而设计的,这样弯曲它没有任何好处。老实说,我觉得阅读和浏览高耸的遗产是件痛苦的事,除非你有一个歌舞升平的IDE,可能需要一周的时间来加载。在保持灵活性的同时,你能实现的扁平化和开放性越近,你在编码方面就越出色,可能会有更多的其他程序员来接替你的工作,他们会感谢你。(显然这是我的看法)

有关原型继承的更多信息,请阅读以下信息性文章:

下面是原型继承的一个示例,应该注意,
Object.create
isPrototypeOf
是相对较新的,对于较旧的JavaScript解释器不存在。但是,在大多数情况下可以使用近似多边形填充

简单地说,当您考虑从任何地方借用方法的对象时,JavaScript变得更加强大,而不是从稍微不太具体的实例严格继承实例;更糟糕的是,构造函数会一次又一次地重建相同的函数

下面只是一个例子,在我编写ECMAScript的16年中,我几乎不需要任何接近经典继承的东西,也不需要在原型链上大量继承的对象。通常我的js基本上只是一些新创建的对象,适当的名称间隔,从固定的函数池借用方法;任何类型的检测都是duck类型的,我会尽可能地将所有内容保持在本地

无论如何,这里有一些我不经常使用的东西:

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
虽然以上内容确实遵循了一种经典的布局,即猴子继承了动物的方法,但您可以用不同的方式处理问题。以下内容对动态更改更开放,事实上,您可以将行为对象完全切换到另一个接口。同样,这只是一个说明,你不必以固定的方式构造事物

我更可能使用的东西:

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({});
你可以调整上面的行为,使其更类似于混合,也就是说,你将采取这些行为,逐步通过它们,并将它们合并到类人猿对象中。。。无论你的目标是什么,它都是开放的

我经常使用的东西:

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')
;
JavaScript需要记住的主要一点是,没有任何函数是由任何东西拥有的,事实上并非如此。每次执行一个函数时,函数的上下文都会通过调用该函数的方式暗示出来,即在调用时计算上下文。这提供了很大的灵活性,并且在您提到调用
函数.apply(context,args)
函数的同时,每次调用
函数都很麻烦;编写自己的系统来隐藏重复是非常容易的

哦,在我忘记之前,还有一件事要从上面的代码中去掉,那就是函数创建没有重复。每个实例在内存中共享相同的函数。如果您计划创建大规模应用程序,这一点很重要,因为您可以通过多个函数实例快速消耗内存

因此,简单回顾一下:

  • 忘记继承吧,许多js项目很少需要它
  • 创建可在需要时扩展的灵活对象
  • 当需要从其他对象借用方法时,使用
    apply
    call
    更改上下文
  • 保持代码的开放性,不需要私密;open更具可扩展性
  • Private否,但具有不可枚举的属性则是另一回事,请参见
  • 确保不复制函数(除非必须),而是创建一次并引用它们

  • 引用事件起源的dom节点或它的子对象javascript对象。按这个顺序

    this.parentNode
    引用dom节点的父节点(不确定它是否在对象上下文中工作)


    当我编写javascript时,我通常会尝试利用html的dom本身,嵌套东西时要注意JS需要如何引用它们。

    问题是你在考虑经典继承,你必须考虑原型继承,因为这就是我们所拥有的<代码>这取决于函数的调用方式,没有魔法,只是在运行时决定,它是动态的,可以是隐式的,也可以是显式的。这就是
    原型
    方法。如果您使用
    new
    ,则
    将是一个实例。很抱歉,我真的不明白您想在这里做什么。您可以显式地将所有方法绑定到当前实例(使用
    this.myMethod=(function(){})。bind(this)
    ,您可以在调用时更改其上下文-简言之,您可以做任何您想做的事。啊,这是另一回事-但是请记住,这些语言显式地使用了public,protect