本文目录一览:
- 1、怎么js理解函数实例
- 2、Js编程语言中,自调用函数是什么?举个Js代码例子解释一下!
- 3、js的执行原理是什么?
- 4、如何将javascript代码编译为c++或java
- 5、javascript框架是什么意思?有什么作用?怎么理解?最好举个例子
- 6、如何用js实现中缀表达式转后缀表达式然后求值
怎么js理解函数实例
js的函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块。如下为其按键驱动时间的一个简单示例
!DOCTYPE html
html
head
script
function myFunction()
{
alert("Hello World!");
}
/script
/head
body
button onclick="myFunction()"点击这里/button
/body
/html
1、JavaScript 函数语法
函数就是包裹在花括号中的代码块,前面使用了关键词 function:
function functionname()
{
这里是要执行的代码
}
当调用该函数时,会执行函数内的代码。
可以在某事件发生时直接调用函数(比如当用户点击按钮时),并且可由 JavaScript 在任何位置进行调用。
提示:JavaScript 对大小写敏感。关键词 function 必须是小写的,并且必须以与函数名称相同的大小写来调用函数。
2、调用带参数的函数
在调用函数时,您可以向其传递值,这些值被称为参数。
这些参数可以在函数中使用。
您可以发送任意多的参数,由逗号 (,) 分隔:
myFunction(argument1,argument2)
当您声明函数时,请把参数作为变量来声明:
function myFunction(var1,var2)
{
这里是要执行的代码
}
变量和参数必须以一致的顺序出现。第一个变量就是第一个被传递的参数的给定的值,以此类推。
实例
button onclick="myFunction('Bill Gates','CEO')"点击这里/button
script
function myFunction(name,job)
{
alert("Welcome " + name + ", the " + job);
}
/script
上面的函数会当按钮被点击时提示 "Welcome Bill Gates, the CEO"。
函数很灵活,您可以使用不同的参数来调用该函数,这样就会给出不同的消息:
实例
button onclick="myFunction('Harry Potter','Wizard')"点击这里/button
button onclick="myFunction('Bob','Builder')"点击这里/button
根据您点击的不同的按钮,上面的例子会提示 "Welcome Harry Potter, the Wizard" 或 "Welcome Bob, the Builder"。
3、带有返回值的函数
有时,我们会希望函数将值返回调用它的地方。
通过使用 return 语句就可以实现。
在使用 return 语句时,函数会停止执行,并返回指定的值。
语法
function myFunction()
{
var x=5;
return x;
}
上面的函数会返回值 5。
注释:整个 JavaScript 并不会停止执行,仅仅是函数。JavaScript 将继续执行代码,从调用函数的地方。
函数调用将被返回值取代:
var myVar=myFunction();
myVar 变量的值是 5,也就是函数 "myFunction()" 所返回的值。
即使不把它保存为变量,您也可以使用返回值:
document.getElementById("demo").innerHTML=myFunction();
"demo" 元素的 innerHTML 将成为 5,也就是函数 "myFunction()" 所返回的值。
您可以使返回值基于传递到函数中的参数:
实例
计算两个数字的乘积,并返回结果:
function myFunction(a,b)
{
return a*b;
}
document.getElementById("demo").innerHTML=myFunction(4,3);
"demo" 元素的 innerHTML 将是:
12
在您仅仅希望退出函数时 ,也可使用 return 语句。返回值是可选的:
function myFunction(a,b)
{
if (ab)
{
return;
}
x=a+b
}
如果 a 大于 b,则上面的代码将退出函数,并不会计算 a 和 b 的总和。
6、局部 JavaScript 变量
在 JavaScript 函数内部声明的变量(使用 var)是局部变量,所以只能在函数内部访问它。(该变量的作用域是局部的)。
您可以在不同的函数中使用名称相同的局部变量,因为只有声明过该变量的函数才能识别出该变量。
只要函数运行完毕,本地变量就会被删除。
7、全局 JavaScript 变量
在函数外声明的变量是全局变量,网页上的所有脚本和函数都能访问它。
8、JavaScript 变量的生存期
JavaScript 变量的生命期从它们被声明的时间开始。
局部变量会在函数运行以后被删除。
全局变量会在页面关闭后被删除。
9、向未声明的 JavaScript 变量来分配值
如果您把值赋给尚未声明的变量,该变量将被自动作为全局变量声明。
这条语句:
carname="Volvo";
将声明一个全局变量 carname,即使它在函数内执行。
Js编程语言中,自调用函数是什么?举个Js代码例子解释一下!
自调用函数:
顾名思义,有2个意思
《1》自行调用的函数:
就是指,函数在页面载入后或者之前就自行调用,无需借助其他函数或方法来启动;
例如:
(function(win){
win.alert(11);
})(window);
《2》自己调用自己的函数:
就是指,递归:在一个函数里面调用自己的函数,当符合一定规则时,跳出自我调用,就是递归。
例如:
var fn = function(n){
if(n == 1) return 1;
else return n * fn(n-1);
}
js的执行原理是什么?
JS是解释执行的,即读取一个语句就执行一个。以前的严格JS是以分号为语句的分隔符,但现在一些浏览器已经接受以换行符为分隔符(似乎是很多人喜欢用基于对象的编程了,而在JS中写对象的函数是需要加分号的,所以很多人都爱忘)。
JS本身只提供语法解析与少部分内部函数支持,其他的均由宿主支持。比如在网页JS中的window, document, navigator等对象,均是由浏览器提供基于其它语言的代码,这些代码通常被隐藏,但很大程度上决定了JS的运行效率。如果你有兴趣,打开Chrome,按F12,调处Console,然后输alert(注意没有()),你就会发现[native code]这个东西。
如何将javascript代码编译为c++或java
java是不能够编译C/C++文件的。他们原理完全不同。背后的运行机制也完全不一样。
C/C++源文件只能够用C/C++的编译器来编译。
以GCC编译器为例,整个编译可以分为四步。
第一步是预处理,包括语法检查等工作。
gcc -P abc.c
第二步由源程序生产汇编语言代码。
gcc -S abc.c
会生成abc.s文件,这个文件里就是汇编代码。
第三步编译器生成目标代码,一个源文件生成一个目标代码。
gcc -c abc.c
会生成abc.o
第四步连接器从目标代码生成可执行文件。
gcc abc.o
目标代码包括机器码和符号表(函数及变量名)。连接器的主要作用是通过符号表在库文件和其他模块中找到在目标代码中引入或未定义的符号(函数及变量名),将几个目标代码合成可执行文件。
javascript框架是什么意思?有什么作用?怎么理解?最好举个例子
浅谈js框架设计 在这个JavaScript框架随处乱跑的时代,你是否考虑过写一个自己的框架?下面的内容也许会有点帮助。
一个框架应该包含哪些内容?
1.语言扩展
大部分现有的框架都提供了这部分内容,语言扩展应当是以ECMAScript为基础进行的,不应当依赖任何宿主环境,也就是说,作为一个框架的设计者,你应当保证你的语言扩展可以工作在任何宿主环境中,而不是仅仅适合浏览器环境。你必须保证把它放到WScript,SpiderMonkeyShell,Rhino Shell,Adobe ExtendScript Toolkit甚至FlashActionScript等环境中都能正确的工作,举个现实一点的例子setTimeout不可以出现在其中,你也不能用XMLHTTP加载脚本运行,尽管它们看起来很贴近语言。保持这一部分的独立性可以让你方便的移植你的框架到其他宿主环境下。
2.数据结构和算法
JS本身提供的内置对象非常有限,很多时候,框架应该提供一些数据结构和算法来帮助使用者更好的完成逻辑表达。但我认为随便翻本数据结构或者算法书用JS挑几个实现了加到框架中是不负责任的,多数数据结构应当以库的形式存在而非框架。框架中的数据结构应该足够常用而且实现不是非常复杂的,可以考虑的如集合、哈希表、链表、有序数组以及有序数组上的二分搜索。对JS来说,对象是一个天然的字符串哈希表,而集合很容易在哈希表上实现,因此只需要处理掉Object的内置方法,我们就可以实现一个高效的集合或哈希表。
3.DOM扩展
JS主要应用于Web开发,目前所有的框架也都用于浏览器环境,那么,浏览器端环境里重点中的重点DOM当然也是框架的扩展目标了,如果一个框架不提供DOM的扩展,那么其实基本没什么用处了。需要注意的是,DOM扩展也有w3c的标准可依,所以,不要尝试为各种浏览器做一些奇怪的扩展,比如FF下面的element们的prototype,框架的编写者应当无视它们。DOM扩展的主要任务之一是兼容性,不同浏览器上的DOM实现相差很多,框架必须消除这些实现带来的差异,提供统一的访问方式。当然,做为框架,应当提供一些更为方便的接口,将宿主提供的DOM对象用js对象封装是个不错的想法,但是同时这也很可能会造成内存泄露,所以做这事之前,了解内存泄露是必要的。实际上,自己想象的扩展远不如W3C的设计,比如如果你能更完整地实现XPath,你就能比JQuery做的更好。
4.AJAX扩展
大部分现有框架出现的原因都是因为AJAX,所以如果你想设计一个受欢迎的框架,AJAX是必须要做的。跟DOM扩展很相似,AJAX扩展的主要任务是兼容和内存泄露,对AJAX的核心组件XMLHttpRequest对象,必须在IE6中使用ActiveX创建,而ActiveX又有各种版本,而随之而来的内存泄露和兼容性变得非常麻烦,比如:事件函数名大小写、this指向、事件函数的null赋值。处理好这些兼容性的基础上,可以做进一步的工作,提供一些常用的实现。应该指出的是,除非你确定你提供的接口比原来的更好,否则不要改变原来的XMLHttpRequest对象的接口,比如写一个Request函数来代替open和send,如果你不清楚W3C的专家们为什么这么设计,请不要把他们想象成傻瓜。我想自己另外写一个兼容且内存安全的XMLHttpRequest加入到自己框架的命名空间里,使它从外部看上去跟W3C描述的XMLHttpRequest一模一样是不错的办法,对XMLHttpRequest我认为唯一可以考虑的修改是提供onsuccess事件。当然针对一些复杂功能的AJAX扩展也是可行的,比如HTMLHttpRequest类似的扩展可以让AJAX初学者喜欢你的框架。
5.效果
时间效果是最能刺激用户神经的,渐隐、缓动、滑动、颜色渐变这些都很不错,其实技术难度也不是很高。拖动效果则是浏览器中一个很重要的效果,用鼠标事件来模拟本来很容易,不过兼容和setCapture也是很麻烦的事情。这一部分内容量力而为就可以了。
7.脚本管理
因为大家非常喜欢C++风格的include或者JAVA风格的import,很多框架提供了基于AJAX的脚本管理,不过同步加载的效率问题是巨大的。之前我们曾经作过各种尝试,希望找到一个浏览器中不用XMLHTTP加载外部js的方法,但是最后得出的结论是:不可能。
关于这个,略微思考就可以知道,Java C++ C#都是编译型语言,include 和import都是编译期处理,在js中做到类似的事情是不太可能的。为了实现类似的功能,我想我们可以利用服务端程序或者编写一个文本工具来实现。
YUI将所有的js文件依赖关系提取出来的做法是可行的,不过这不能算是include的实现方式了,维护依赖关系不是一件很简单的事情。
8.控件
EXT的成功告诉我们:提供优质的控件才是框架的王道。你不能指望优质的扩展会吸引更多使用者。多数人只关心如何快速完成手边的工作。当然不是所有框架都要提供这部分内容。控件好坏取决于能力和美工,不过至少要保证框架里的控件不会内存泄露。
框架设计的若干原则:
1.不要做多余的事
对这框架设计来说,我认为一个非常必要的原则就是不要做多余的事情,举个极端的的例子:
function add(a,b)
{
return a+b;
}
这样的代码如果出现在框架中,就是个十足的笑话。不过大多数时候,事情不是那么明显,很多框架试图用某种形式在JS中"实现"OOP,但是实际上,JS本身是OO的(ECMA262中明确指出来的,不像某些人所说是基于对象云云)只是有一些语法跟Java等语言不同。那么显然这些OOP的"实现"其实是跟上面的例子一样的道理。另一个例子是Array.prototype.clone
Array.prototype.clone=function(){
return this.slice();
}
2.慎用prototype扩展
很多框架利用修改原生对象的prototype来做语言扩展,但我认为应当小心地看待这件事,毫无疑问这将造成一定的命名污染,你无法保证框架的使用者或者与你的框架共存的其他框架不会使用同样的名字来完成其他的事情。特别需要注意的是,Object和Array这两个对象的prototype扩展格外的危险,对Object来说,如果Object被修改,那么框架的使用者将无法创建一个未被修改的干净的对象,这是一个致命的问题,尤其如果你的使用者喜欢用forin来反射一个对象的属性。Array.prototype修改的危险来自js一个不知有意还是无意的小小设计,对原生的Array来说,任何情况下for和forin的遍历结果是相同的,而因为无法控制自定义的属性是不可枚举的,任何Array.prototype的修改都会破坏这种特性。一方面,我认为不应当推荐用forin遍历数组,这其中包含着错误的语义。另一方面,框架的设计者必须尊重这些使用者,因为对于ECMA所定义的语法而言,它是正确的做法。其中包含着这样一个简单的事实:假如你的框架中修改了Array.prototype,那么一些之前能正确工作的代码变得不可正确工作。
直接修改prototype看上去非常诱人,但是在考虑它之前应当先考虑两种可能的方案:
(1)函数
提供一个以对象为第一个参数的函数比如 Array.prototype.each =
function ForEach(arr,f)
{
if(arr instanceof Array)/*...*/;
}
(2)继承
以return的形式继承一个内置对象 比如考虑Array.prototype.each=
function ArrayCollection()
{
var r=Array.apply(this,arguments);
r.each=function(){/*......*/};
return r;
}
套用一句名言,不要修改原生对象的prototype,除非你认为必要。不过修改原生对象的prototype确实有一些特殊的用途(就是"必要的情况"),主要体现在2点:文字量支持和链式表达。举一个例子可以体现这两点:
var cf=function f(a,b,c,d)
{
/*........*/
}.$curry(3,4).$curry(5).$run();
如果希望实现类似上面的表达方式,可能就需要扩展Function.prototype,权衡一下的话,如果你认为命名污染的代价是值得的,那么也是可以提供给使用者的。
一个比较讨巧的办法是把选择权利交给使用者,提供一个扩展器:
function FunctionExtend()
{
this.$curry=function(){/*......*/};
this.$run=function(){/*......*/};
}
如果用户喜欢可以FunctionExtend.apply(Function.prototype); 如果不喜欢扩展 则可以
var r=function(){/*......*/};
FunctionExtend.apply(r);
3.保持和原生对象的一致
不知你有没有注意到,内置对象Function Array等都有这样的性质:
new Function()跟Function的结果完全一致(String Number Boolean这种封装型对象没有这样的性质)
如果框架中提供的类也具有这种性质,会是不错的选择。这仅仅是一个例子,如果你注意到了其他细节,并且让框架中的类和原生对象保持一致,对使用者来说是非常有益的。
4.尊重语言 尊重用户
编写框架应该尊重依赖的语言环境,在对原有的元素修改之前,首先应该考虑到原来的合理性,任何语言的原生环境提供的都是经过了精心设计的,在任何修改之前,至少应该考虑这几点:效率、命名规范、必要性、与其他功能是否重复。如果你没有付出至少跟语言的设计者相当的工作量,你的做法就是欠考虑的。
编写框架也应该尊重用户的所有习惯,将编写者的喜好强加给使用者并不是框架应该做的事情。框架应该保证大部分在没有框架环境下能运行的代码都能在框架下正常工作,这样用户不必为了使用你的框架而修改原有的代码。
5.规范命名和使用命名空间
减少命名污染可以让你的框架跟其他框架更好地共存。很多框架使用了命名空间来管理,这是良好的设计。命名应该是清晰且有实际意义的英文单词,如前面3所述,为了保持和原生对象的一致,命名规则最好贴近原生对象,比如类名第一字母大写,方法名用驼峰命名。捎带一提prototype中的$实在是非常糟糕的设计,无法想象$出现的目的仅仅是为了让使用者少写几个字母。这种事情应该交给你的用户在局部代码中使用
如何用js实现中缀表达式转后缀表达式然后求值
逆波兰表达式,它的语法规定,表达式必须以逆波兰表达式的方式给出。逆波兰表达式又叫做后缀表达式。这个知识点在数据结构和编译原理这两门课程中都有介绍,下面是一些例子:
正常的表达式 逆波兰表达式
a+b --- a,b,+
a+(b-c) --- a,b,c,-,+
a+(b-c)d --- a,d,b,c,-,,+
a=1+3 --- a=1,3 +
http=(smtp+http+telnet)/1024 写成什么呢?
http=smtp,http,telnet,+,+,1024,/
逆波兰表达式是一种十分有用的表达式,它将复杂表达式转换为可以依靠简单的操作得到计算结果的表达式。例如(a+b)(c+d)转换为ab+cd+
它的优势在于只用两种简单操作,入栈和出栈就可以搞定任何普通表达式的运算。其运算方式如下:
如果当前字符为变量或者为数字,则压栈,如果是运算符,则将栈顶两个元素弹出作相应运算,结果再入栈,最后当表达式扫描完后,栈里的就是结果。
将一个普通的中序表达式转换为逆波兰表达式的一般算法是:
(1)首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。
(2)读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。
(3)从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。
(4)如果不是数字,该字符则是运算符,此时需比较优先关系。
做法如下:将该字符与运算符栈顶的运算符的优先关系相比较。如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。倘若不是的话,则将栈顶的运算符从栈中弹出,直到栈顶运算符的优先级低于当前运算符,将该字符入栈。
(5)重复上述操作(3)-(4)直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,我们便可以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。
下面是程序化算法流程:
1、建立运算符栈stackOperator用于运算符的存储,压入'\0'。
2、预处理表达式,正、负号前加0(如果一个加号(减号)出现在最前面或左括号后面,则该加号(减号)为正负号) 。
3、顺序扫描表达式,如果当前字符是数字(优先级为0的符号),则直接输出该数字;如果当前字符为运算符或括号(优先级不为0的符号),则判断第4点 。
4、若当前运算符为'(',直接入栈;
若为')',出栈并顺序输出运算符直到遇到第一个'(',遇到的第一个'('出栈但不输出;
若为其它,比较stackOperator栈顶元素与当前元素的优先级:
如果 栈顶元素 = 当前元素,出栈并顺序输出运算符直到 栈顶元素 当前元素,然后当前元素入栈;
如果 栈顶元素 当前元素,直接入栈。
5、重复第3点直到表达式扫描完毕。
6、顺序出栈并输出运算符直到栈顶元素为'\0'。
各运算符及符号优先级:
'\0': -1
')': 1
'(': 2
'+'、'-': 3
'*'、'/'、'%': 4
'^': 5
其它: 0
/**
* 计算逆波兰表达式的值
*/
function calculate(RPolishArray){
var result = 0;
var tempArray = new Array(100);
var tempNum = -1;
for(i = 0;i RPolishArray.length;i++){
if(RPolishArray[i].match(/\d/)){
tempNum++;
tempArray[tempNum] = RPolishArray[i];
}else{
switch(RPolishArray[i]){
case '+':
result = (tempArray[tempNum-1] *1) + (tempArray[tempNum] * 1);
tempNum--;
tempArray[tempNum] = result;
break;
case '-':
result = (tempArray[tempNum-1] *1) - (tempArray[tempNum] * 1);
tempNum--;
tempArray[tempNum] = result;
break;
case '*':
result = (tempArray[tempNum-1] *1) * (tempArray[tempNum] * 1);
tempNum--;