作者senser (彷佛曾经一起死过)
看板Ajax
标题Re: [问题] 根据 if 决定叫用哪一个function
时间Wed Sep 21 13:12:01 2011
虽然跟原po问题无关
但好像有人对为什麽
function my_function(){
do some stuff
}
这种写法不好感到好奇
在网路上 这篇文章有很详细的解释
http://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/
但可能大家懒得看英文 所以看看我能不能解释一下 可能有点长..
首先js里有一个东西 叫做hoisting
意思就是"提起来" "拉起来"
那到底是拉甚麽东西哩?
当我们作一个declaration 被browser解读时 他会自动被放到他context的最上面
比如说:
(function(){
alert(my_var);
var my_var = 'say something man';
})();
这里不会产生js的ReferenceError
因为在 interpreter 眼里是长这样
(function(){
var my_var = undefined;
alert(my_var);
my_var = 'say something man';
})();
my_var已经被定义了(虽然是assign "undefined" object)
所以firebug里不会看到 ReferenceError: my_var is not defined
那这和function有甚麽关系哩
比较以下两例:
(function(){
my_func();
var my_func= function(){
alert('yo');
};
})();
(function(){
my_func();
function my_func(){
alert('yo');
};
})();
第一个会有 TypeError: my_func is not a function
第二个则会跑出"yo"
因为他被解读为
(function(){
var my_func = undefined;
my_func();
my_func= function(){
alert('yo');
};
})();
(function(){
function my_func(){
alert('yo');
};
my_func();
})();
有看到差异了吗?
在hoisting中 declaration会被整个搬上去
而var xx = function yy(){};这种写法
只有左边的部分是declaration 所以搬上去时 右边不见了
这意味着甚麽呢?
function yy(){};这种写法 在同一个context里
不管你写在哪 全部都呼叫的到 和顺序无关
有人会说 这超好的呀 网路script就是要随便写都通 要forgiving一点
这当然没错 就像var就有变数 管他甚麽型别
但是其实这种code在维护上有很大的缺点
1.
这某种层度像是种变数污染
感觉还没写过的东西 上面却叫得出来
或是不小心用到了同样名字 会产生难预料又难debug的问题
2.
Overwrite问题:
(function(){
function sayHelloThenHi(){
alert('hello');
}
sayHelloThenHi();
function sayHelloThenHi(){
alert('hi');
}
sayHelloThenHi();
})();
这会有甚麽结果呢? 他会跟你讲两声hi
直观上这是我们想要的吗?
(function(){
var sayHelloThenHi=function(){
alert('hello');
}
sayHelloThenHi();
sayHelloThenHi = function(){
alert('hi');
}
sayHelloThenHi();
})();
此例中 他会先说hello在说hi
感觉似乎是我们比较想要的结果
至於为什麽? 相信你已经知道了
结论:
那到底要怎麽写function比较好呢
1.
如果你JAVA或是C#等等classical的语言实在太强了
为什麽要为js这种诡异的prototypal语言改习惯??
那千万记住把function xxx(){}这种东西写在每个context的最前面
这就可以省掉大部分错误和麻烦
(这也就是很多js的书说宣告变数要在最前面)
2.
如果你想钻研js这诡异的语言
你的function应该大部分会出现在你global abatement的object下面
如
var MySite = {
my_awesome_func : function(){
//do something good
}
};
MySite.my_awesome_func(); //invoke
或是expression的写法
var callback = function(){
do some useful stuff
};
这常常用於callback的传递...
总之你应该不会有机会写
function bad(){
//still do something
}
这种东西
真是抱歉 讲太多废话了.. 一打就很难停下来..
因为国内有少数教材 常会有不是很正确的观念
让我以前刚学习时 走了不少冤枉路
以至於看到种观念有关的东西 我就特别想讲
加上js又是很特别的语言 常常有人用其他语言的逻辑来套
但事实上含意是不同的
希望有人有耐心可以看到这里
如果有错误 也希望可以指正:D
※ 引述《senser (彷佛曾经一起死过)》之铭言:
: 您可能对於js的function宣告方式没有很清楚
: 但我想可能很多人也有不正确的认识
: js的function宣告方式分为两种
: function declaration和function expressions
: 主要会因为hoisting 而有些微的不同
: invoke的方式 大概分为四种
: 主要和this的binding有关
: 在这例子中 您的设计想法是完全可行且合理的
: 只是实做上要注意
: 首先如果你加了() 就是一种invocation
: 意思就是执行这function
: 所以应该写成
: $(selector).mousedown(function(){
: if(using IE){
: func1(); //invoke
: }else {
: func2(); //invoke
: }
: });
: 如果你不直接invoke
: 应该用function expression
: 因为functon declaration绝不应出现在{}block中
: 在if中作function declaration
: 每个browser对这种错误会有不同的奇怪诠释
: (新的browser supports 所谓的 function statement)
: 再者也有可能因为hoisting而overwrite的问题产生
: if(using IE){
: var myHandler = func1;
: }else {
: var myHandler = func2;
: }
: $(selector).mousedown(myHandler); //function copying
: 有兴趣可以参考这两篇
: http://kangax.github.com/nfe/
: http://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/
: ※ 引述《coldollsheep (加油加油^^)》之铭言:
: : 不好意思 问一个比较粗浅的问题
: : 我做了一个按钮 点了会有声音
: : IE 跟其他浏览器是采用不同的方法
: : 如以下程式码
: : 可以看到我毎次点击都必须判断一次
: : //关键那颗钮
: : $('#click_btn').mousedown(function (ev)
: : {
: : //1.处理音效
: : if ($.browser.msie)
: : {
: : document.getElementById("soundeffect").src=soundfile;
: : } else
: : {
: : var _audio2 = document.createElement('audio') ;
: : _audio2.src = soundfile ;
: : _audio2.play()
: : }
: : }
: : ----
: : 有没有办法变成这样
: : func1()
: : {
: : 实际内容
: : }
: : func2()
: : {
: : 实际内容
: : }
: : //1.处理音效
: : if ($.browser.msie)
: : {
: : playsound() = func1(); <------这里就是关键 我不知道怎麽弄这里
: : 观念不好不好意思
: : } else
: : {
: : playsound() = func2();
: : }
: : //关键那颗钮
: : $('#click_btn').mousedown(function (ev)
: : {
: : //1.处理音效
: : playsound();
: : }
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 71.104.219.9
※ 编辑: senser 来自: 71.104.219.9 (09/21 13:23)
1F:推 mrbigmouth:推清楚明白 尤其是当你需要让function的内容依情况而有 09/21 14:30
2F:→ mrbigmouth:所改变时 一定不能用function xxx()的写法 09/21 14:30
3F:推 ChowMein:简单说就是 var 和 function declaration 的差异 09/21 18:33
4F:推 tcling:写的太好了! 09/22 13:39
5F:推 No:好文~ 09/22 18:28
6F:→ tyf99:我是把 var=func() 当做是 function pointer 09/22 19:03
7F:→ tyf99:C 会有重复宣告错误,js 重复宣告是後面的宣告会覆盖前面的 09/22 19:05