注册 登录
编程论坛 JavaScript论坛

请大家帮忙看看:如何在事件处理函数中重定向"this"?

netwind007 发布于 2010-12-14 04:41, 1701 次点击
我定义了一个对象,它会自动生成两个DIV,并把它们插入到<body></body>中,但我希望这两个DIV在对象中是private的。我想给其中一个DIV添加一个CLICK事件,当它被CLICK时,会改变另一个DIV的背景色。由于这两个DIV在对象中是private的,所以我专门写了一个函数来做这件事。整个代码如下:
程序代码:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www. xmlns="http://www. xml:lang="en" lang="en">
    <head>
        <title>Test Page</title>
        <script type="text/javascript">
            function MyClass(){
                this._oDiv1 = document.createElement("div");
                this._oDiv1.style.cssText = "width:200px; height:150px; background-color:#0c0";
                document.body.appendChild(this._oDiv1);
               
                this._oDiv2 = document.createElement("div");
                this._oDiv2.style.cssText = "width:150px; height:30px; background-color:#f55; color:black; margin-top:10px; text-align: center";
                this._oDiv2.innerHTML = "Change to blue";
                document.body.appendChild(this._oDiv2);
            }
            MyClass.prototype.addClick = function(){
                this._oDiv2.onclick = function(){
                    this._oDiv1.style.backgroundColor = "#00c";    //problem happens here
                    return false;
                };
                //alert(this._oDiv2.onclick.toString());
            };
           
            function start(){
                var o = new MyClass();
                o.addClick();
            }
        </script>
    </head>
    <body onload="start();">
    </body>
</html>
其中MyClass.prototype.addClick便是用来给this._oDiv2添加click事件的,但是这段代码不起作用,原因出在this._oDiv1.style.backgroundColor = "#00c";这一句:这里的this本应指向对象的当前实例,但在这里却指向了产生CLICK事件的那个元素(即_oDiv2),结果导致错误。我不知道该如何让这里的this正确的指向当前对象实例?请大家指点一下。先谢谢了。
28 回复
#2
netwind0072010-12-14 05:52
刚才去国外的网站搜索了一下(英文不太好,换了好几回搜索词),找到了一个解决办法,供大家参考。

解决办法就是用闭包:
MyClass.prototype.addClick = function(){
    var that = this;
    this._oDiv2.onclick = function(){
         that._oDiv1.style.backgroundColor = "#00c";
         return false;
    };
};

谢谢大家。
#3
hugeannex2010-12-14 09:17
那也不是private的呀!
#4
foktime2010-12-14 09:46
顺便出个小题目
程序代码:
name = 'window';
var Fun = function() {
this.name = 'Fun';

this.show = function() {
return function() {
alert(this.name);
}
}
};

var Test = function() {
this.name = 'Test';
this.msg = new Fun().show();
};

new Test().msg();
猜弹出啥 为什么
#5
netwind0072010-12-14 14:37
回复 3楼 hugeannex
你是指_oDiv1和_oDiv2吗?

其实本质上,javascript的object没有private成员,我们只是在逻辑上把它们当成private来看,这就是为什么我要定义一个function来绑定事件处理,而不是让用户直接用
o._oDiv1.onclick = "...";
来绑定事件处理——因为这样就暴露了_oDiv1。

谢谢。
#6
netwind0072010-12-14 15:20
以下是引用foktime在2010-12-14 09:46:03的发言:

顺便出个小题目
var name = 'window';
var Fun = function() {
this.name = 'Fun';
 
this.show = function() {
return function() {
alert(this.name);
}
}
};
 
var Test = function() {
this.name = 'Test';
this.msg = new Fun().show();
};
 
new Test().msg();猜弹出啥 为什么
版主这道题出得好呀!我自己试了一下,虽然和一开始想的结果不一样(呵呵,这是婉转的说法,其实就是答错了),但我的思路是正确的。

我一开始想的是“window”,因为我知道return function(){alert(this.name);}是把alert(...)返回到上一级执行,所以其作用域是上一级,但我一开始忽视了Test这一级(马虎了),不知怎的就把上一级想成了global,所以想结果是“window”。

其实,这道题的本质就是:
var Test = function(){
    this.name = 'Test';
    this.msg = function(){alert(this.name);}
}
结果当然是“Test”。

Javascript的this指代有时候是有点绕人,而且经常惹祸,不像C#里的this一向规规矩矩老实巴交,以后得多留意。

呵呵,不知我的回答版主是否满意,还请多多指教。
#7
foktime2010-12-14 15:31
-2333

[ 本帖最后由 foktime 于 2013-11-12 16:19 编辑 ]
#8
netwind0072010-12-14 15:40
回复 4楼 foktime
刚才想去投版主一票,顺便挣50分,结果因为是新人,被剥夺了民主权力。唉,啥时论坛里能实现普选呀?
#9
foktime2010-12-14 15:42
回复 6楼 netwind007
回答基本正确 这是绕个小弯而已 呵呵
js的this很灵活,具体指向谁一定要结合上下文
设计代码的时候在使用this时也要很清楚自己要做什么,一不小心就指飞老
#10
foktime2010-12-14 15:47
以下是引用netwind007在2010-12-14 15:40:27的发言:

刚才想去投版主一票,顺便挣50分,结果因为是新人,被剥夺了民主权力。唉,啥时论坛里能实现普选呀?
那你就声援一下吧  咱们版选版主不存在竞争,有人选就会中,因为人不多 呵呵

有没有选举权要看在版里的活跃度,其实多发几个帖子你就有选举权了,只是为了防止马甲作弊
#11
netwind0072010-12-14 15:53
以下是引用foktime在2010-12-14 15:31:25的发言:


function MyClass(){
    var temp = "";
    function test(){
        //code
    }
}temp不叫MyClass的私有属性叫什么;test不叫MyClass的私有方法又叫什么
作为C#出身的javascript菜鸡(鸡也是“鸟”),每当提到private和public,你猜我脑子里首先浮现出的是谁?

肯定不是“董存瑞”,而是传达室的张大爷,呵呵...——为什么?因为private和public主要是定义类成员的可访问性,public成员向所有类用户公开,就像单位的对外接待部门,而private成员只供类内部的其它成员访问,比如领导的秘书。所以,当我说"私有"属性时,主要是指其可“访问性”这层意思。
#12
netwind0072010-12-14 15:56
以下是引用foktime在2010-12-14 15:47:40的发言:

那你就声援一下吧  咱们版选版主不存在竞争,有人选就会中,因为人不多 呵呵

有没有选举权要看在版里的活跃度,其实多发几个帖子你就有选举权了,只是为了防止马甲作弊
嗯,我明白了,不是剥夺我的民主权力,而是拿我当“未成年”儿童了。
#13
foktime2010-12-14 16:02
回复 11楼 netwind007
例子里的私有属性和方法在外部也是访问不到的 再说下去就有些较真了 呵呵
语言之间的差异 我们不好拿C#的private去理解js的。


[ 本帖最后由 foktime 于 2010-12-14 16:26 编辑 ]
#14
foktime2010-12-14 16:05
有时间你也可以多去C#版 去帮人解决解决问题 自己也会有提高  那个版也够冷的 发个问题经常一天没人理
#15
netwind0072010-12-14 16:19
以下是引用foktime在2010-12-14 16:02:38的发言:

例子里的私有属性和方法在外部也是访问不到的 再说下去就有些较真了 呵呵
语言之间的差异 我们不好拿C#的private去理解js的。
版主指的那个,叫“成员”,Javascript类的所有成员都是可访问的;版主所说的“访问不到”,其实不是访问不到,而是没有清楚地告诉javascript解释器要访问哪个对象里的成员——所以,概念还是应该树立清楚。其实,javascript里也有“私有”概念,就是变量开始的“_”,虽然这概念是存在于程序员头脑中。
#16
netwind0072010-12-14 16:21
以下是引用foktime在2010-12-14 16:05:54的发言:

有时间你也可以多去C#版 去帮人解决解决问题 自己也会有提高  那个版也够冷的 发个问题经常一天没人理
我是看了网上的推荐才来这里的,觉得这里应该人气旺一些。
#17
foktime2010-12-14 16:55
以下是引用netwind007在2010-12-14 16:19:33的发言:

版主指的那个,叫“成员”,Javascript类的所有成员都是可访问的;版主所说的“访问不到”,其实不是访问不到,而是没有清楚地告诉javascript解释器要访问哪个对象里的成员——所以,概念还是应该树立清楚。其实,javascript里也有“私有”概念,就是变量开始的“_”,虽然这概念是存在于程序员头脑中。
版主所说的“访问不到”,其实不是访问不到,而是没有清楚地告诉javascript解释器要访问哪个对象里的成员——所以,概念还是应该树立清楚。
.................我震撼了

无语了 学识浅薄,我期待达人们来帮忙解读一下下- -
#18
hugeannex2010-12-15 09:34
以下是引用netwind007在2010-12-14 15:40:27的发言:

刚才想去投版主一票,顺便挣50分,结果因为是新人,被剥夺了民主权力。唉,啥时论坛里能实现普选呀?
哭个P啊,我老将了,还不是不能投!
#19
hugeannex2010-12-15 09:37
以下是引用foktime在2010-12-14 09:46:03的发言:

顺便出个小题目
name = 'window';
var Fun = function() {
this.name = 'Fun';
 
this.show = function() {
return function() {
alert(this.name);
}
}
};
 
var Test = function() {
this.name = 'Test';
this.msg = new Fun().show();
};
 
new Test().msg();猜弹出啥 为什么
这题多年前都有人问了,一般不是人家不懂,而是不是自己写的,被绕来绕去绕晕了。
#20
foktime2010-12-15 09:47
回复 19楼 hugeannex
这个,不是从网上什么地方抄来的 和朋友练习着玩的时候给出的 就这几个代码不至于 如有雷同纯属巧合了。
出个题不也就这么几种考法么,简单小题目而已 旨在初步掌握this的用法!
#21
foktime2010-12-15 09:48
回复 18楼 hugeannex
投了你一票。不过似乎没什么用,这次选举貌似是无效的  可能是票数太少吧。
#22
foktime2010-12-15 10:00
hugeannex,劳驾你顺便也给我讲解一下上面一仁兄的一段话:

版主所说的“访问不到”,其实不是访问不到,而是没有清楚地告诉javascript解释器要访问哪个对象里的成员——所以,概念还是应该树立清楚。


俺好长长学识。
对于这样一段代码
程序代码:
var Fun = function(){
    var name = "test";
}
Fun.prototype = {
    //定义方法
}

我怎么着才能清楚地告诉javascript解释器我想要从外部访问Fun里的私有成员了

这都可以的话,我是不是可以理解为其他语言的private其实也是没清楚的告诉编译器怎么去访问

别告诉我在构造函数中写特权方法,这不能用来解释“清楚地告诉javascript解释器要访问哪个对象里的成员”


[ 本帖最后由 foktime 于 2010-12-15 10:33 编辑 ]
#23
sclorg2010-12-15 16:52
感觉var that = this;就是承上启下作用的一段代码
#24
冰镇柠檬汁儿2010-12-15 20:27
以下是引用sclorg在2010-12-15 16:52:24的发言:

感觉var that = this;就是承上启下作用的一段代码
错,这句的意思是记住当前位置this的指向,因为这句后面的代码this的指向就是另一个东西了
#25
冰镇柠檬汁儿2010-12-15 20:33
回复 22楼 foktime
私有成员就是在类的内部实现中可以共享的成员。但是并不对外公开,JavaScript中并没有特殊的机制来定义私有成员,但是可以用一些技巧来实现这个功能。主要是通过变量的作用域性质来实现的,在一个函数内部定义的变量称为局部变量,该变量不能被函数外的程序所访问,可以被函数内部定义的嵌套函数所访问。
在类的构造函数中可以为类添加成员,通过这种方式定义的成员,实际上共享了在构造函数内部定义的局部变量,这些变量就可以看作是类的私有成员。如:
实现私有成员
<script>
function class1(){
var pp="this is a private property";//私有属性成员pp
function pm(){//私有方法成员pm,显示pp的值
      alert(pp);
}
this.method1=function(){//在公有成员中改变私有属性的值
      pp="pp has been changed";
}
this.method2=function(){
    //在公有成员中调用私有方法
    pm();
}
}
var obj1 = new class1();
obj1.method1();
obj1.method2();
</script>
注意:
局部变量(私有成员)被所有在构造函数中定义的公有方法所共享,而且仅被在构造函数中定义的公有方法所共享,这意味着,在prototype中定义的类成员不能访问在构造器中定义的局部变量。
实现静态成员:
和私有成员勉强相比,静态成员就要正统的多了,静态成语就是属于一个类的成员,如:
function class1(){

}
class1.staticProperty="sample";
class1.staticMethod=function(){
    alert(class1.staticProerty);
}
class1.staticMethod();
如果要给每个函数对象都添加通用的静态方法,还可以函数对象所对应的类Function来实现:
Function.prototype.showArgsCount=function(){
    alert(this.length);
}
function class1(a){
}
class1.showArgsCount();
由此可见,通过Function的prototype原型对象,可以给任何函数都加上通用的静态成员。
#26
foktime2010-12-16 08:54
回复 25楼 冰镇柠檬汁儿
你复制了一大通基础知识,但非我想要看到的。

严格来说,js不存在类的概念,我们只能说是在写模拟类

我只是针对上面提到的那句话,希望有人能给出个支持那话的论据,怎么着能清楚地告诉javascript解释器要访问哪个对象里的私有属性或方法,概念怎么树立才叫清楚


[ 本帖最后由 foktime 于 2010-12-16 09:00 编辑 ]
#27
foktime2010-12-16 08:56
特想见识一下,外部访问对象私有属性、方法的高超手段
#28
foktime2010-12-16 09:05
以下是引用sclorg在2010-12-15 16:52:24的发言:

感觉var that = this;就是承上启下作用的一段代码
建议你仔细看下我前面出的小题,看明白了这地方你自然就懂了
#29
sclorg2010-12-16 09:22
不用咬文嚼字,我并非不理解,我只是通俗的记忆,对于初学者,不用讲一大堆道理,时间长了反而记不住,只要记住这儿缺少一段起什么作用的代码,究其原理任何一个会google的人都会明白
1