Javascript面向对象编程指南笔记 - 第三章 - 函数

本文是关于JavaScript面向对象编程的第三章,主要讲解函数的概念、预定义函数的使用,如parseInt()、parseFloat()等,并探讨函数的作用域、变量作用域、匿名函数、回调函数、自调函数和内部函数等高级特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第三章 函数


3-1 什么是函数

所谓函数,本质上就是一种代码的分组形式。
我们将一组代码赋予名字,便于日后调用。

通常来说,函数声明 通常由一下几个部分组成:

  • function 子句
  • 函数名称
  • 函数所需参数,通常有0到多个参数,参数之间用逗号分割。
  • 函数所执行代码块,称之为函数体。
  • return 子句。如果没有显式的返回值,我们就默认为返回值是undefined

需要注意的是,一个函数只有一个返回值,如果需要返回多个值,可以考虑放进一个数组中,以数组元素的形式返回。


3-1-1 调用函数

如果要使用一个函数,就必须要调用它。
调用方式:函数名+(参数)。

>>> var result = sum(1,2);
>>> result;
>>> 3
//调用sun()函数,返回值赋予result.

3-1-2 参数

通常定义函数时,我们会设置函数所需参数,当然如果不设置,或者调用时忘记传递数值,Javascript就会自动将其设定为undefined

>>> sum(1);
NaN
// 因为只设置了一个参数,所以函数将 1 与 undefined 相加。

对于所以传递来的参数,JS来者不拒。
所以即使参数传递过多,多余部分会被忽略掉

其实,我们可以创建一些在参数数量方面更为灵活的函数。 这得益于每个函数内部都有一个内建的 arguments 数组, 它能返回函数所接收的所有参数

>>> function args() { return arguments; }
>>> args();
[]
>>> args(1, 2, 3, 4, "haha");
[1, 2, 3, 4, "haha"]

通过 arguments 数组,我们能进一步完善sum()函数功能, 使之能对任意数量的参数执行求和运算。

function sumOnSteroids() {
    var i, res = 0;
    var number_of_params = arguments.length;
    for (i = 0; i < number_of_params; i++) {
        res += arguments[i];
    }
    return res;
}
// arguments.length 返回的事函数所调用时所接收的参数数量。
// (其实arguments不是一个数组,而是一个类似数组的对象,第四章会解答)

3-2 预定义函数

Javascript 引擎中有一组可以供随时调用的内建函数。


3-2-1 parseInt( )

parseInt()会试图将其收到的任何输入值(通常是字符串)转换成整数类型输出。如果转换失败就返回NaN。

>>> parseInt('064');
064
>>> parseInt('abc123');
Nan
>>> parseInt('1abc123')//注意第一位是数字
1
>>> parseInt('123abc')
123

除此之外,该函数还有个可选的第二参数:radix, 它负责设定函数所期望的数字类型-十进制,二进制,八进制,十六进制等。如果我们以十进制输出FF,结果为NaN,如改为十六进制,结果为255。

>>> parseInt('FF', 10);
NaN
>>> parseInt('FF', 16);
255

通常如不设置第二参数,函数默认为十进制。
但如果首参字符串为0x开头,第二参数默认为十六进制。
如果0开头,默认为八进制。


3-2-2 parseFloat( )

功能和parseInt( )基本相同,不过只支持转换为十进制
与parseInt( )相同,在遇到第一个异常字符时会放弃
与parseInt( )不同的是,parseFloat( )可以接收指数形式的数据。

>>> parseFloat('123e-2');
1.23

3-2-3 isNaN( )

可以通过此函数确定某个输入值是否是可以参与算术运算的数字。
因此可以来测试parseInt()和parseFloat()的调用成功与否。

>>> isNaN(NaN)
true
>>> isNaN(123)
false
>>> isNaN(1.23)
false
>>> isNaN(parseInt('abc123'))
true

注:NaN === NaN 返回值是false


3-2-4 isFinite( )

检查输入是否为既非 infinity 也非 NaN 的数字


3-2-5 URL的编码与反编码

在URL(Uniform Resource Locator)或 URI 中有一些字符具有特殊含义,因此我们需要转义.
* encodeURI():返回一个可用的URL 解码:decodeURI()
* encodeURIComponent(): 认为我们所传递的仅仅是URL的一部分。解码:decodeURIComponent()


3-2-6 eval( )

会将输入字符串当做Javascript代码来执行。

>>> eval('var ii = 2;');
>>> ii;
2

避免使用 避免使用 避免使用


3-2-7 alert( )函数

不是JS核心一部分,不在ECMA标准中,由浏览器提供,显示文本消息对话框。

但是这个函数会阻塞当前浏览器进程,也就是说代码会停止执行

3-3 变量的作用域

在JS中,不能为变量定义特定的作用域。
但是可以定义函数域。
如果变量是在某个函数中定义的,那么函数以外不可见。
但如果在 if 或 for 中定义,在代码块外可见

全局变量 定义在所有函数之外
局部变量 定义在函数中

如果声明变量时没有用 var 语句,变量默认为全局变量


3-4 函数也是数据

其实函数也是一种 数据类型

function f(){return 1;}
var f = function(){return 1;}//函数标识记法 function literal notation

对函数变量调用 typeof ,返回字符串为 function

JS中, 函数是一种数据,只不过这种数据有两个重要特性:

  • 它们包含是代码
  • 它们是可执行的

因为函数也赋予变量数据,所以函数命名规则与一般变量相同 —— 即函数名不能以数字开头, 可以由任意的字母,数字和下划线组合。

3-4-1 匿名函数

没有被赋予任何变量的数据叫做 匿名数据

没有名字的函数叫做 匿名函数

>>> function(a){return a;}

我们可以将匿名数据片段设置为函数,这样就有了两种优雅的用法:

  • 我们可以将匿名函数作为参数传递给其他函数 ,这样,接收方函数就能利用我们所传递的函数来完成某些事情。
  • 我们可以定义某个匿名函数来执行某些一次性任务。

下面为实例:

3-4-2 回调函数

既然函数可以像其他数据那样赋值给某个个变量,可以被定义,删除,拷贝,那么也可以当场参数传递给其他函数。

下面我们定义一个以两个函数为参数的函数。

function invoke_and_add(a,b){
    return a() + b();
}
function one(){
    return 1;
}
function two(){
    return 2;
}
>>> invoke_and_add(one,two);
3

事实上我们可以用匿名函数来代替 one() 和 two()。

invoke_and_add(function(){return 1;}, function(){return 2;})

3-4-3 回调函数

在编程过程中,我们通常需要将一个函数的返回值传递给另一个函数。

function multiplyByTwo(a, b, c) {
    var i, ar = [];
    for(i = 0; i < 3; i++) {
        ar[i] = arguments[i] * 2;
    }
    return ar;
}
function addOne(a) {
    return a + 1;
}

>>> multiplyByTwo(1, 2, 3);
[2, 4, 6]
>>> addOne(100);
101

下面我们定义一个用于储存元素数组,实现三个元素在两个函数之间传递。

var myarr = [];
myarr = multiplyByTwo(10, 20, 30);
[20, 40, 60]

然后,用循环遍历每个元素, 并将它们分别传递给 addOne()。

>>> for (var i = 0; i < 3; i++){myarr[i] = addOne(myarr[i]);}
>>> myarr
[21, 41, 61]

在这里我们还是使用了两个循环。
我们需要对multiplyByTwo()函数做一些改动, 使其接受一个回调函数。

function multiplyByTwo(a, b, c, callback){
    var i, ar = [];
    for(i = 0; i < 3; i++){
        ar[i] = callback(arguments[i] * 2);
    }
    return ar;
}

现在我们只需要调用一次函数。

>>> myarr = multiplyByTwo(1, 2, 3, addOne);
[3, 5, 7]

我们还可以用匿名函数代替addOne(), 这样可以节省一个额外的全局变量。

>>> myarr = multiplyByTwo(1, 2, 3, function(a){return a + 1});
[3, 5, 7]

3-4-4 自调函数

(
    function(){
        alert('');
    }
)()
// 这种匿名函数可以在定以后自行调用
(
    function(name){
        alert('Hello ' + name + '!');
    }
)('dude') //立即调用

自调函数不会产生任何全局变量,但是是无法重复执行。
更加适合一次性的或初始化的任务。


3-4-5 内部(私有)函数

我们可以在函数内部定义另一个函数

function a(param){
   function b(theinput){
       return theinput * 2;
   };
   return 'The result is ' + b(param);
};
var a = function(param){
   var b = function(theinput){
       return theinput * 2;
   };
   return 'The result is ' + b(param);
};//函数标识记法

当调用全局函数a()时,本地函数b()会在内部调用,由于是本地函数,在外部是不可见的,所以也叫私有函数。

好处:

  • 有助于我们确保全局名字空间的纯净性(命名冲突小)
  • 私有性——只讲必要函数暴露给“外部世界”

3-4-6 返回函数的函数

函数都会有一个返回值,及时不是显式返回,也会隐式返回一个 undefined,我们也可以返回一个函数。

function a() {
    alert('A!');
    return function(){
        alert('B!');
    };
}

如果想让返回的函数立刻执行,可以在后面加上一堆括号。

>>> a()();

3-4-7 能重写自己的函数

由于一个函数可以返回另一个函数, 因此我们可以用新的函数来覆盖旧的。

>>> a = a();//用a()的返回值来重写自己。

我们其实也可以在函数内部重写函数自身

function a() {
    alert('A!');
    a = function(){
        alert('B!');
    };
}

第一次调用执行 alert(“A!”)
第二次执行alert(“B!”)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值