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