JavaScript 函数
2.1 初始函数
在 JavaScript 中,函数类似于 Java 中的方法,是执行特定功能的 JavaScript 代码。但是 JavaScript 中的函数使用更简单,不用定义函数属于哪个类,因此调用时不需要用"对象.函数名()"的方式。直接使用函数名称来调用函数即可。
JavaScript 中有函数有两种:一种时 JavaScript 自带的系统函数,另一种时用户自行创建的自定义函数。
2.1.1 系统函数
在 JavaScript 中, 常用的系统函数有三种,分别是 parseInt()、parseFloat() 和 isNaN()。其中前两种函数时用于将非数字的原始值转换成数字的函数.最后一种系统函数是用于检查是否是非数字的函数。
1.parseInt()
parseInt() 函数可以解析一个字符串,并返回一个整数,语法
parseInt("字符串");
在判断字符串是否为数字前,paseInt() 和 paseFloat() 都会分析该字符串。parseInt() 函数首先查看下标为 0 的字符,判断它是否为一个有效数字。如果不是,则返回 NaN,不在继续执行其他操作。
var num1=parseInt("56.64"); //返回值为56
var num1=parseInt("123abc"); //返回值为123
var num1=parseInt("hello999"); //返回值为NaN
var num1=prompt("请输入第一个数");
var num2=prompt("请输入第二个数");
var parInt1=parseInt(num1);
var parInt2=parseInt(num2);
var result=parInt1+parInt2;
document.write("两个数相加之和为:"+result);
2.parseFloat()
parseFloat() 函数可以解析一个字符串,并返回一个浮点数,语法
parseFloat("字符串");
parseFloat() 函数与 parseInt() 函数的处理方式相似,从下标 0 开始查看每个字符,直到找到第一个非有效的字符为止,然后把该字符之前的字符串转换为浮点数。对于 parseFloat() 函数来说,第一个出现的小数点是有效字符,如果有两个小数点,那么第二个小数点被看做无效。
var num1=parseFloat("3.1415926"); //返回值为 3.1415926
var num1=parseFloat("123abc"); //返回值为 123
var num1=parseFloat("hello999"); //返回值为 NaN
var num1=parseFloat("52.18.97"); //返回值为 52.18
3.isNaN()
isNaN() 函数用于检查其参数是否是非数字,语法
isNaN(x);
如果 x 是特殊的非数字,则返回 true;否则返回 false。
var num1=isNaN("20.5"); //返回值为 false
var num1=isNaN("123abc"); //返回值为 true
var num1=isNaN("48.98"); //返回值为 false
isNaN() 函数通常用于检测 oarseInt() 函数和 parseFloat() 函数的结果,以判断它们标识的是否为合格的数字,也可以用 isNaN() 函数来检测算术是否错误。
2.1.2 自定义函数
与 Java 语言一样,JavaScript 需要先定义函数,然后才能调用函数。而在 JavaScript 中,定义函数的方式有两种,分别是函数声明和函数表达式。
1.函数声明
在 JavaScript 中,函数声明由关键字 function、函数名、一组参数及大括号中待执行的 JavaScript语句组成。
语法
function 函数名(参数1,参数2,。。。。。){
//JavaScript 语句;
[return 返回值]
}
function 时定义函数的关键字,必须有;参数是函数的参数。因为JavaScript 本身是弱类型语言,所以它的参数没有类型检查和类型限定。函数中的参数是可选的,根据函数是否带参数,可分为不带参数的无参函数和带参数的有参函数。不带参数语法
function 参数名(){
//JavaScript 语句;
}
return 语句用来规定函数返回的值。要执行一个函数,必须先调用这个函数,当调用函数时,必须指定函数名及其后面的参数(如果有参数)。函数的调用一般和元素的事件结合使用。语法
事件名="函数名()";
示例
function study()
{
for (let i = 0; i <5 ; i++) {
document.write("
欢迎学习 JavaScript
")}
}
study() 是创建的无参函数;onclick 标识按钮的单击事件,当单击按钮时调用函数 study()。
效果图
运行一次,页面只能输出5行 “欢迎学习 JavaScript” 。如果需要根据用户的要求每次输出不同的行数,需要用到有参构造函数。语法
function study(count)
{
for (let i = 0; i document.write("欢迎学习 JavaScript
")
}
}
count 表示传递的参数,不需要定义数据类型,将 prompt() 方法返回的值作为参数传递给函数 study(count)。
2.函数表达式
在 JavaScript 中,把一个函数赋给一个变量,此时形成了函数表达式。语法
var 变量=function(参数1,参数2,参数3,....){
//JavaScript 语句;
}
既然有两种定义函数的发昂视,说明二者一定有不一样的地方。下面使用函数声明的方式定义两个函数名都为 f1() 的函数。使用函数表达式的方式定义脸啊哥哥函数名都为 f2() 的函数。
//函数声明
function f1(){
console.log("今天天气真好!");
}
f1();
function f1(){
console.log("今天天气好晴朗,处处好风光");
}
f1();
var f2=function (){
console.log("哇");
}
//函数表达式
f2();
var f2=function (){
console.log("娃哈哈~");
}
f2();
使用函数声明的方式定义两个函数名相同的函数,后面的函数会覆盖掉前面的函数;而使用函数表达式的方式定义函数,会从上到下逐行执行代码输出结果。
2.1.3 函数自调用
与 Java 不同的是,在自定义函数中,如果函数有名字,如 “function study(){}”,则被称为命名函数;如果函数没有名字,如"function(){}",则被称为匿名函数。
(function(){
//函数体
})();
将 “function(){}” 匿名函数放在一对"()" 中,就实现了调用,被称为函数自调用。
特点
没有名字;在声明的同时直接调用;不会出现命名冲突。
2.1.5 回调函数
//字符串类型作为参数使用
function f1(x,y){
console.log(x+y);
}
f1("hello","你好");
function f2(x){
console.log(x);
}
f2(true);
function f1(fn){
console.log("f1函数调用了");
fn();
}
function f2(){
console.log("f2函数调用了");
}
f1(f2);
f2 函数作为参数传递到 f1() 中,并且在 f1() 函数中执行 fn() 函数,这时,f2() 函数可以被称作回调函数。如果没有指定函数名称,可以被称作匿名回调函数。
2.2 局部变量和全局变量
在 JavaScript 中,根据变量作用范围的不同,可分为局部变量和全局变量。
2.2.1 局部变量和全局变量的概念及使用
局部变量实在函数内部声明的变量(必须使用 var) ,只能在函数内部访问它。特点是可以在不同的函数中使用名称相同的局部变量。全局变量是在函数外声明的变量,网页上的所有脚本和函数都能访问它。
//全局变量
var x=10;
function f1()
{
//局部变量
var y=5;
console.log(x);
console.log(y);
}
f1();
全局变量和局部变量的区别:作用域不同、声明位置不同、生存期不同。
作用域:局部变量仅作用在函数中,而全局变量作用于整个脚本。声明位置:局部变量声明的位置在函数中,而全局变量可以声明在使用之前的任何位置。生存期:局部变量在函数运行以后被删除,而全局变量在页面关闭后被删除。
2.2.2 隐式全局变量
局部变量实在函数内部声明的变量(必须使用var)。如果变量声明时没有var,责备称为隐式全局变量。语法
var a1=1; //全局变量
a2=2; //隐式全局变量
在函数内部声明一个局部变量
function f1(){
num=200; //num按理说应该是一个局部变量
}
f1(num);
num本应时局部变量,但没有使用 var 来声明,所以变成了一个隐式全局便令,在函数外部可以访问到num。
2.3 作用域和作用域链
2.3.1 作用域和块级作用域
作用域(Scope) 就是变量与函数的可访问范围,即作用域控制这变量与函数的可见性和生命周期。块级作用域是由大括号限定的。在块级作用域下,所有的变量都定义在大括号内,从定义开始到大括号结束这个范围内可以使用,除了这个范围就无法访问。
//正常带有大括号的语句
{
var num=10;
}
console.log(num);//10
if(true)
{
var num=20;
}
console.log(num);//20
for (let i = 0; i < 5; i++) {
var num=30;//30
}
console.log(num);//30
//函数
function f1(){
var num=50;
}
f1();
console.log(num);
结果依次为 10、20、30 会报错。
在前三种大括号的情况里面定义的变量,在大括号外面也能使用,即违背了块级作用域的概念。
结论
JavaScript 没有块级作用域。
f1() 函数内部定义的变量 num 在外部无法访问,原因是在函数作用域下,变量只在函数内部存在。
2.3.2 作用域链
当查找变量的时候,会先从当前上下文的变量对象中查找,如果没有找到,就会从父级执行上下文的变量对象中查找,一直找到全局上下文的变量对象,即全局对象。这样由多个执行上下文的变量对象构成的链表就被成为作用域链(Scope Chain)
var num=10; //在script标签里面定义的变量,就是0级作用域
function f1(){
var num=20; //1级作用域
function f2(){
var num=30; //2级作用域
function f3(){
var num=50; //3级作用域
console.log(num); //50
}
f3();
}
f2();
}
f1();
运行时会发现,控制台输出的值为50.根据作用域链的概念,一开始执行函数时,现在内部找变量,在内部已经找到,因此就得到了 50.如果 3 级作用域中没有 var num =50,则会向上一级查找,那么输出的就是30.如果 2 级作用域没有 var num=30,就会继续向上找,直到找到为止。如果最终没有找到,则会报错。
2.4 闭包
在函数外部无法读取函数内的局部变量,而闭包是指有权访问另一个函数作用域中的变量的函数。主要分为两部分
在函数的内部,在定义一个函数。把内部的函数作为返回值。
function f1(){
var num=1;
function f2(){
alert(num)
}
returnf2;
}
var result=f1();
result();
f1() 外层函数中声明了一个内部函数 f2(),然后通过 f2() 去操作 f1() 的局部变量,最后把内部函数 f2() 作为返回值。
代码中的内部函数 f2() 就是闭包。
可以把闭包简单地理解成 “定义在函数内部的函数。”
闭包主要的作用
可以读取函数内部的变量可以让这些变量的值始终保存在内存中。
闭包的缺点
由于闭包可以读取函数内部的变量,所以闭包可以在父函数外部改变父函数内部变量的值。闭包会是的函数中的变量都被保存在内存中,所以内存消耗大。
不能滥用闭包,否则会造成网页性能的问题。
2.5 事件
事件介绍onload一个压敏啊或一幅图像完成加载。onclick鼠标单击某个对象。onmouseover鼠标指针移到某元素上。onmouseout鼠标指针离开某元素onkeydown某个键盘按键被按下onchange域的内容被改变。读取函数内部的变量
可以让这些变量的值始终保存在内存中。闭包的缺点
由于闭包可以读取函数内部的变量,所以闭包可以在父函数外部改变父函数内部变量的值。闭包会是的函数中的变量都被保存在内存中,所以内存消耗大。
不能滥用闭包,否则会造成网页性能的问题。
2.5 事件
事件介绍onload一个压敏啊或一幅图像完成加载。onclick鼠标单击某个对象。onmouseover鼠标指针移到某元素上。onmouseout鼠标指针离开某元素onkeydown某个键盘按键被按下onchange域的内容被改变。