- 浏览: 440220 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (162)
- easymock (3)
- 模板引擎 (3)
- JForum (4)
- web (9)
- spring (10)
- java (20)
- struts (9)
- uml (3)
- java pattern (19)
- JQuery (14)
- 多线程 (13)
- database (21)
- PS (3)
- ejb (6)
- 版本管理 svn , maven , ant (2)
- protocol (1)
- 测试 (1)
- ws (7)
- Apache (4)
- 脚本语言 (1)
- guice (1)
- 分布式 (4)
- 架构 (0)
- 经验 (1)
- 版本管理 svn (1)
- maven (1)
- ant (1)
- 书籍 (1)
- Linux (1)
最新评论
-
Master-Gao:
稍微明白了点,,有点萌萌哒
为什么匿名内部类参数必须为final类型 -
waw0931:
终于明白了,谢谢!
为什么匿名内部类参数必须为final类型 -
十三圆桌骑士:
提供了两个链接还是有用的。
安装Mondrian -
放方芳:
[flash=200,200][/flash]
Freemarker标签使用 -
放方芳:
[b][/b]
Freemarker标签使用
英文原版: http://devlicio.us/blogs/sergio_pereira/archive/2009/02/09/javascript-5-ways-to-call-a-function.aspx
Time after time I find JavaScript code that has bugs caused by lack of proper understanding of how functions work in JavaScript (a lot of that code has been written by me, by the way.) JavaScript has functional programming characteristics, and that can get in our way until we decide to face and learn it.
For starters, let's examine five ways to invoke a function. On the surface we might be tempted to think that functions work exactly like C#, but we will see that there are important differences and ignoring them will undoubtedly result in hard to track bugs.
Let's first create a simple function that we will be using through the
rest of this post. This function will just return an array with the
current value of this
and the two supplied arguments.
<script type="text/javascript">
function makeArray(arg1, arg2){
return [ this, arg1, arg2 ];
}
</script>
Most common way, unfortunately, global function calls
When we are learning JavaScript we learn how to define functions using the syntax used in the example above. We learn that it's also very easy to call that function — all we need to do is:
Wait a minute. What's that window
object doing there? Why is it the value of this
? If you haven't stopped to think about it, please stay with me here.
In JavaScript, and I'm not talking specifically about the browser here,
there's a default/global object. It's as if every code that we write
which seems to be just "loose" inside your script (i.e. outside of any
object declaration) is actually being written in the context of that
global object. In our case, that makeArray
function isn't
just a loose "global" function, it's a method of the global object.
Bringing ourselves back to the browser, the global object is mapped to
the window
object in this environment. Let's prove that.
alert( typeof window.methodThatDoesntExist );
// => undefined
alert( typeof window.makeArray);
// => function
What all this means is that calling makeArray
like we did before is the same as calling as follows.
I say it's unfortunate that this is the most common way because it leads us to declare our functions globally by default. And we all know that global members are not exactly the best practice in software programming. This is especially true in JavaScript. Avoid globals in JavaScript, you won't regret it.
myFunction()
, causes the value of this
to be the default object (window
in the browser).
Method call
Let's now create a small object and use the makeArray
function as one of its methods. We will declare the object using the literal notation. Let's also call this method.
//creating the object
var arrayMaker = {
someProperty: 'some value here',
make: makeArray
};
//invoke the make() method
arrayMaker.make('one', 'two');
// => [ arrayMaker, 'one', 'two' ]
// alternative syntax, using square brackets
arrayMaker['make']('one', 'two');
// => [ arrayMaker, 'one', 'two' ]
See the difference here? The value of this
became the object itself. You may be wondering why isn't it still window
since that's how the original function had been defined. Well, that's just the way functions are passed around in JavaScript. Function
is a standard data type in JavaScript, an object indeed; you can pass
them around and copy them. It's as if the entire function with argument
list and body was copied and assigned to make in arrayMaker
. It's just like defining arrayMaker
like this:
var arrayMaker = {
someProperty: 'some value here',
make: function (arg1, arg2) {
return [ this, arg1, arg2 ];
}
};
obj.myFunction()
or obj['myFunction']()
, causes the value of this
to be obj
.
This is a major source of bugs in event handling code. Look at these examples.
<input type="button" value="Button 1" id="btn1" />
<input type="button" value="Button 2" id="btn2" />
<input type="button" value="Button 3" id="btn3" onclick="buttonClicked();"/>
<script type="text/javascript">
function buttonClicked(){
var text = (this === window) ? 'window' : this.id;
alert( text );
}
var button1 = document.getElementById('btn1');
var button2 = document.getElementById('btn2');
button1.onclick = buttonClicked;
button2.onclick = function(){ buttonClicked(); };
</script>
Clicking the first button will display "btn1"
because it's a method invocation and this
will be assigned the owner object (the button input element.) Clicking the second button will display "window"
because buttonClicked
is being called directly (i.e. not like obj.buttonClicked()
.)
This is the same thing that happens when we assign the event handler
directly in the element's tag, as we have done for the third button.
Clicking the third button does the same of the second button.
That's another advantage of using a library like jQuery. When defining
event handlers in jQuery, the library will take care of overriding the
value of this
and make sure it contains a reference to the element that was the source of the event.
//using jQuery
$('#btn1').click( function() {
alert( this.id ); // jQuery ensures 'this' will be the button
});
How does jQuery override the value of this
? Keep reading.
Two more: apply()
and call()
The more you leverage functions in JavaScript, the more you find
yourself passing functions around and needing to invoke them in
different contexts. Just like jQuery does in the event handler
functions, you'll often need to override the value of this
. Remember I told you functions are objects in JavaScript? Functions have predefined methods, two of them are apply()
and call()
. We can use them to do precisely that kind of overriding.
var gasGuzzler = { year: 2008, model: 'Dodge Bailout' };
makeArray.apply( gasGuzzler, [ 'one', 'two' ] );
// => [ gasGuzzler, 'one' , 'two' ]
makeArray.call( gasGuzzler, 'one', 'two' );
// => [ gasGuzzler, 'one' , 'two' ]
The two methods are similar. The first parameter will override this
. They differ on the subsequent arguments. Function.apply()
takes an array of values that will be passed as arguments to the function and Function.call()
takes the same arguments separately. In practice I believe you'll find that apply()
is more convenient in most cases.
this
without copying the function to another object, we can use myFunction.apply( obj )
or myFunction.call( obj )
.
Constructors
I won't delve into the details of defining types in JavaScript but at
minimum we should be aware that there aren't classes in JavaScript and
that any custom type needs a constructor function. It's also a good idea
to define the methods of your type using the prototype
object, which is a property of the constructor function. Let's create a small type.
//declaring the constructor
function ArrayMaker(arg1, arg2) {
this.someProperty = 'whatever';
this.theArray = [ this, arg1, arg2 ];
}
// declaring instance methods
ArrayMaker.prototype = {
someMethod: function () {
alert( 'someMethod called');
},
getArray: function () {
return this.theArray;
}
};
var am = new ArrayMaker( 'one', 'two' );
var other = new ArrayMaker( 'first', 'second' );
am.getArray();
// => [ am, 'one' , 'two' ]
What's very important to note here is the presence of the new
operator before the function call. Without that your function will just
be called like a global function and those properties that we are
creating would be created on the global object (window
.)
And you don't want to do that. Another issue is that, because you
typically don't have an explicit return value in your constructor
function, you'll end up assigning undefined
to some variable if you forget to use new
.
For these reasons it's a good convention to name your constructor
functions starting with an upper case character. This should serve as a
reminder to put the new
operator before the call.
With that taken care of, the code inside the constructor is very similar
to any constructor you probably have written in other languages. The
value of this
will be the new object that you are trying to initialize.
new MyFunction()
, the value of this
will be a brand new object provided by the JavaScript runtime. If we don't explictly return anything from that function, this
will be considered its return value.
It's a wrap
I hope understanding the differences between the invocation styles help
you keeping bugs out of your JavaScript code. Some of these bugs can be
very tricky do identify and making sure you always know what the value
of this
will be is a good start to avoiding them in the first place.
发表评论
-
js this理解
2015-01-22 16:23 521http://www.jb51.net/article/162 ... -
AJAX提交Struts2表单(服务器端validation校验出错提示)
2012-12-27 17:00 14241.目标 在基于Struts2的应用中,利用AJ ... -
jquery小技巧
2012-12-21 16:38 7461.怎么访问js函数里面的函数? 1.re ... -
如何写jquery插件
2012-10-16 16:06 845参考一下链接: http://www.cnblogs. ... -
js 闭包
2012-10-16 15:50 950我的博客里面已经有好几篇介绍java script closu ... -
validationEngine 结合struts2 ajax验证
2011-10-26 14:36 1514项目中用到validation Engine 和 stuts2 ... -
jquery处理带有特殊字符的id
2011-10-26 14:30 7944所以id最好不要取名有 “.”、“#”、“(”、“[” ... -
struts2 json
2011-10-26 14:29 1251为了方便ajax调用传输数据,在struts2中加入的js ... -
js 闭包
2011-10-24 22:51 1185最近在网上查阅了 ... -
jquery 验证框架
2011-10-19 18:22 16034Jquery validate 验证 具体查看附件中demo ... -
javascript面向对象技术基础
2011-08-22 16:40 886看了很多介绍javascript面向对象技术的文章,很晕.为什 ... -
Javascript的匿名函数
2011-08-22 14:19 853Javascript的匿名函数 一、什么是匿名函数? ... -
JQuery原型
2011-05-23 11:20 3117在 JavaScript 中,每个函 ...
相关推荐
android demo,webview_js(webview的js方法调用java方法)。
JavaScript调用C#方法并获得返回参数
jsp 日期 日历js方法调用 简单 方便 好用 <script language="javascript" type="text/javascript" src="My97DatePicker/WdatePicker.js"> ()"> 文件夹请放到WebRoot下! 单击文本框就可调用日期
vbscript和javascript互相调用方法
Android中调用js方法及js中调用本地方法,简单明了
Winform中使用CefSharp和js互相调用方法,Winform中使用CefSharp和js互相调用方法,Winform中使用CefSharp和js互相调用方法,Winform中使用CefSharp和js互相调用方法 vs2019.debug目录下有cef所需要的文件,在其他...
前台js与后台C#互相调用 这里总结的很好,拿来了,另外加了点说明 C#代码与javaScript函数的相互调用
link中调用js方法 link中调用js方法link中调用js方法link中调用js方法
在WebView页面上的按钮点击事件响应本地类中的方法。
js调用后台方法 js JS调用后台 JS后台方法 用到了[WebService]特性
用javascript代码调用delphi写的函数
C#与JAVASCRIPT函数的相互调用 C#调用JAVASCRIPT函数的调用 JAVASCRIPT调用C#函数的调用
” rel=”external nofollow” rel=”external nofollow” rel=”external nofollow” ,其中[removed]是伪协议,它可以让我们通过一个链接来调用javascript函数.而采用这个方式 [removed];可以实现A标签的点击事件...
JS调用后台带参数的方法
Struts2动态方法调用 包括 1.js方法调用 2.普通的表单提交调用 3.通配符
这里是 VC与JavaScript交互(三) ———— JS调用C++,下载的时候需要看清楚
android demo,android调用h5中的js方法,js方法在input中写入值,android中的java方法调用该js方法。
android和js互相调用,并且可以传参数。
一个在HTML中使用Javascript的window.external调用C#内函数的示例程序。该方法可应用于网页程序开发中的网页-程序沟通,例如用C#的IHTMLWindow2.execScript替换HTML默认Javascript方法使其直接与C#传参、通讯。
主要介绍了android webview中使用Java调用JavaScript方法并获取返回值,本文直接给出代码示例,需要的朋友可以参考下