【有书共读】JavaScript面向对象编程指南3
3.1、什么是函数
所谓函数,本质上是一种代码的分组形式。我们可以通过这种形式赋予某组代码一个名字,一般之后的调用。
函数声明由以下几部分组成:
·关键词function
·函数名称
·函数所需的参数。一个函数通常有0个或多个参数。参数之间用逗号分隔。
·函数所有执行的代码块,称之为函数体。
·return子句
注意:一个函数只能有一个返回值,如果需要同时返回多个值,可以考虑将其放进一个数组里,以书元素的形式返回。
3.1.1、调用函数
调用方法:只需在函数名后面加一对用以传递参数的括号即可。
3.1.2、参数
参数分为:形参(形式参数)与实参(实际参数)
形参是指定义函数时所用的那些参数;
实参是在调用函数时所传递的那些参数。
举例:
>function sum(a,b){
return a+b;
}
>sum(1,2);
这里a和b是形参,1和2是实参。
函数内部的arguments变量是内建变量,每个函数中都能调用。它能返回函数所接收的所有参数。
Arguments.length返回的是函数被调用时所接收的参数数量。
3.2、预定义函数
可随时调用的内建函数包括:
·parseInt();
·parseFloat();
·isNaN();
·IsFinite();
·encodeURI();
·decodeURI();
·encodeURIComponent();
·dencodeURIComponent();
·eval();
3.2.1、parseInt()
parseInt()会试图将其收到的任何输入值(通常是字符串)转换成整数类型输出。如果转换失败就返回NaN。
如:
>parseInt(‘123’);
123
该函数还有可选的第二个参数:基数(radix),它负责设定函数所期望的数字类型——十进制、十六进制、二进制等。
如果未制定第二个参数,函数默认为十进制。两种情况除外:
·如首参数字符串是0x开头,第二参数将默认为16进制;
·如首参数字符串是0开头,第二参数将默认为8进制;
ECMAScript5移除了八进制的默认表示法。
>parseInt(‘FF’,16);
255
>parseInt(‘0377’);
255
>parseInt(‘0x77’);
887
3.2.2、parseFloat();
parseFloat()的功能与parseInt()基本相同,只是它仅支持讲述入职转换为十进制数。因此,该函数只有1个参数。
parseFloat()还可以接受指数形式的数据。
>parseFloat(‘123e-2’);
1.23
3.2.3、isNaN()
通过isNaN()确定某个输入值是否是一个可以参与算术运算的数字。该函数可以用来检测parseFloat()和parseInt()的调用是否成功与否。
NaN自己不存在等值的概念,表达式NaN===NaN返回的是false。
3.2.4、IsFinite()
IsFinite()可以用来检查输入是否是一个既非Infiity也非NaN的数字。
3.2.5、URI的编码与反编码
在URL或URI中,有一些字符是具有特殊含义的。如果想“转义”这些字符,就可以去调用函数encodeURI()或encodeURIComponent();前者会返回一个可用的URL,后者会认为我们所传递的仅仅是URL的一部分。
编码:encodeURI('http://www.baidu.com?name=zhang@xiao@jie&order=1')
结果:"http://www.baidu.com?name=zhang@xiao@jie&order=1"
编码:encodeURIComponent('http://www.baidu.com?name=zhang@xiao@jie&order=1')
结果:"http%3A%2F%2Fwww.baidu.com%3Fname%3Dzhang%40xiao%40jie%26order%3D1"
反编码函数:decodeURI()和dencodeURIComponent()
3.2.6、eval()
eval()会将其输入的字符串当做javascript代码来执行。不过需要尽量避免使用它。
>eval(‘varii=2;’);
>ii;
2
3.3、变量的作用域
变量是以函数做为作用域的。
也就是说变量在某个函数中定义的,那么在函数以外的地方是不可见的。“全局变量”指的是定义在所有函数之外的变量(也就是定义在全局中的变量);“局部变量”则是在某个函数中定义的变量。
注意:如果声明一个变量时没有使用var语句,该变量就会被默认为全局变量。
变量提升
当JavaScript执行过程红进入新的函数时,这个函数内被声明的所有变量都会被移动(或者提升)到函数最开始的地方。这个概念很重要,必须牢记。
注意:被提升的只是变量的声明,这意味这,只有函数体内声明的这些变量在该函数执行开始时就存在,而与之相关的赋值操作并不会被提升,它还在其原来的位置上。
3.4、函数也是数据
函数也是一种数据,可以把函数赋值给一个变量。
函数这种特殊的数据类型有2个特性:
·所包含的是代码
·是可执行的 (或者说是可调用的)
调用函数,只需要在它的名字后面加一对括号即可。
函数命名规则与一般变量相同——函数名不能以数字开头,并且可以由任意的字母、数字、下划线和美元符号组合而成。
3.4.1、匿名函数
没有命名的函数称为匿名函数。
var f = function(){
Return a;
}
匿名函数的两种用法:
·将匿名函数做为参数传递给其他函数;
·可以定义某个匿名函数来执行某些一次性任务。
3.4.2、回调函数
函数可以像其它数据那样被定义、删除、拷贝,以及当成参数传递给其他函数。
当将函数A传递给函数B,并由B来执行A时,A就成了一个回调函数(callback functions)。如歌这时A还是一个无名函数,我们就称它为匿名回调函数。
什么时候使用回调函数?使用回调函数的优势,包括:
·可以在不做命名情况下传递函数(可以节省变量名的使用);
·可以将一个函数调用操作委托给另一个函数(节省一些代码编写工作);
·有助于提升性能。
3.4.3 回调示例
3.4.4.即时函数
匿名函数的另一应用示例——可以在定义后立即调用。
·将匿名函数的定义放进一对括号中,然后外面再紧跟一对括号即可。其中,第二对括号起到的是“立即调用”的作用。
(
funciton(){
Albert(‘boo’);
}
)();
·也可以将第一对括号闭合于第二对括号之后。
(
funciton(){
Albert(‘boo’);
}()
);
即时函数优点:不会产生任何全局变量;
缺点:无法重复执行。
3.4.5、内部(私有)函数
在函数A内部定义一个函数B,函数B在函数A以外的地方是不可见的可以称为私有函数。
好处在于:
·有助于确保全局名字空间的纯净性;
·确保私有性。
3.4.6、返回函数的函数
每个函数都有一个返回值,如果这个返回值是一个函数,就是返回函数的函数。
funciton a(){
albert(‘A’);
Return funciton(){
albert(‘B’);
};
}
调用:将该返回值赋值给某个变量,就可以像使用一般函数那样去调用了。
>var newFunc = a();
>newFunc();
上面第一行执行的是albert(‘A’);第二行执行的才是albert(‘B’);
3.4.7、能重写自己的函数
用新的函数覆盖旧的函数,以避免每次调用时重复一些不必要的操作。
>a = a();
或者
funciton a(){
albert(‘A’);
a = funciton(){
albert(‘B’);
};
}
3.5、闭包
3.5.1、作用域链
在函数A中定义了另一个函数B,那么B中可以访问的变量既来自它自身的作用域,也可以来自其父级作用域。这就形成了一条作用域链(scope chain),该链的长度(或深度)则取决于我们的需要。
3.5.2、利用闭包突破作用域链
N突破作用域链:只需要将它们升级为全局变量(不适用var语句)或通过F传递(或返回)给全局空间即可。
闭包#1
函数F中多了返回N,而在函数N中多了返回变量b,这样N和b都可以通过作用域链进行访问。
var a = ”global variable”;
var F = function(){
var b = “local variable”;
var N = function(){
var c=”inner local”;
return b;
};
return N;
};
闭包#2
在函数体内创建一个新的全局函数inner()
var inner;//placeholder
var F = function(){
var b = “local variable”;
var N = function(){
return b;
};
inner = N;
};
相关定义与闭包#3
如果一个函数会在其父级函数返回之后留住对父级作用域的链接的话,相关闭包就会被创建起来。但其实每个函数本身就是一个闭包,因为每个函数至少都有访问全局作用域的权限,而全局作用域是不会被破坏的。
循环中的闭包(没看懂)
Getter与setter
getter 是一种获得属性值的方法,setter是一种设置属性值的方法
需要将getter和setter这两种函数放在一个共同的函数中,并在该函数中定义secret变量,这是的两个函数能够共享同一作用域。
迭代器
通常情况下我们知道如何用循环来遍历一个而简单的数组,但有时我们需要对更复杂的数据结构,它们通常会有着与数组截然不同的序列规则。这时就需要将一些谁是下一个的复杂逻辑封装成易于使用的next()函数,人后,我们需要简单地调用next()就能实现对于相关的遍历操作了。
Function setup(x){
Var i = 0;
Return function(){
Return x[i++];
};
}
调用
>var next = setup([‘a’,’b’,’c’]);
>next();
“a”
>next();
“b”
>next();
“c”
#Java##笔记##读书笔记#