javascript入门(2):函数基础

适合javascript和前端初学者,读者应该有c或java语言基础,至少了解c或java的变量、数据和数据类型,同时应该已经懵懵懂懂地写过一点Javascript代码,至少知道如何利用网页和浏览器来编写和运行javascript代码。这系列文章并不是试图代替网上海量的正统的javascript教程,而是针对这些教程给出一种更有效、更直达灵魂的学习参考,特别适合那些“感觉自己会一点,但又不是很会”的初学者。

前置的知识是要掌握javascript的变量和数据,参考主流的教程,或者参考笔者的这一篇《javascript入门(1):变量和数据》

本篇是关于javascript函数的基础入门,仅限于介绍全局函数,以便于掌握函数的一些基础知识。暂不涉及到类里的函数,后续进阶篇章会详细介绍类和类里的函数。

函数声明和定义

先看一段代码:

var i = 10086;

首先,函数在javascript中是作为一种数据类型存在的。也就是说,函数有和var i = 10086一样的声明和赋初值形式(在函数范畴内按惯例通常不叫“赋初值”而叫做“定义”,下文采用“定义”的说法)。这一点,比较接近于c语言的风格,但是与java的风格差异很大(毕竟,java是面向对象的,而不是面向函数或过程的),对java比较熟练的读者,要抛开java的思维定式,真正接纳一般数据和变量的思想,记住,函数在javascript里面也只是个数据。

函数的声明和定义也是一样的形式:

var 函数变量 = 函数的值或者叫函数的定义但注意不是返回值;

【声明】声明的形式和其他任何数据类型都是一样的:

var f;

【定义】函数定义的形式如下:

function(参数列表){
    函数体
}

简单描述如下:

1、定义必须以function打头,这就类似于java实例化一个对象要写new关键字;

2、紧跟着function的是圆括号包围的参数(形参)列表,多个参数之间用逗号隔开,不必声明参数的类型,直接写出参数名即可;

3、紧跟着参数列表的是花括号包围的函数体,这和c/java基本一致;

有c/java编程基础的读者,如果阅读过主流的javascript入门教程,就马上会提出质疑:上段代码中没有给出“函数名”!在大多数主流教程中首次介绍函数所给出来的写法如下(差别就在于function后面有函数名):

function f(参数列表){
    函数体
}

注意,这种写法我个人称之为“javascript函数的c语言变体”(纯个人称法),简称为“c变体函数”。可以理解为javascript语言设计者为了迎合熟悉c语言的程序员而不得已支持的编程形式。“c变体函数”其实是给很多javascript初学者带来困惑的根源,也非常不利于解释javascript函数一些区别于c/java语言的行为特性。

请务必了解:

function f(参数1,参数2){
    return true;
}
// 上面是“c变体函数”,其实就是下面这种写法的一个等价,而下面这种写法更利于学习javascript
var f = function(参数1,参数2){
    return true;
}
// 特别注意上述两种写法中,函数名f出现的位置不同。不要简单地理解为位置不同,要真正理解变量声明、数据赋值的形式

上述两种写法等价地做到了:声明一个函数变量名叫f,完成了它的“数据赋值”(函数定义)。实际编程中你可以灵活使用两种形式的任一种,但心中必须非常清楚,var f = function(){}的形式才是“本体”,做到“望变体而心有本体”,对于后面学习高级技术非常重要。

最后,看一下函数变量的类型,进一步加强一下对“函数本质”的理解:

var f = function(){};
console.log(typeof f); // function

var i = 10086;
console.log(typeof i); // number
console.log(typeof g); // function. 函数变量同样有“变量提升”机制
function g(){}
console.log(typeof g); // function. g是所谓“函数名”,但本质上是个指代函数的变量

函数调用

调用就很接近于c/java了。

var f = function(){
  console.log('Hello World!')
};
f(); // 函数调用,打印 Hello World!

特殊的点表现在:形参列表和实参列表不必100%对应一致:

var f = function(i, j){
  console.log(i); // 1 形参实参对应的,直接传入
  console.log(j); // undefined 形参对应不到实参的,不会被赋值,其值是undefind
};
f(1); // 调用,实参少于形参

var g = function(i){
  console.log(i); // 1 形参实参对应的,直接传入
  // 多余的实参没有形参与之对应的,直接忽略,不会被传入   
};
g(1, 2); // 调用,实参多余形参

形参会与实参从左端开始尝试一一对应,对应上的,实参值传递给形参;形参多出来的会被赋值undefined;实参多出来的直接被忽略,不传入。

形参实参这个传递机制,变相地实现了类似于面向对象的“多态”。定义一个函数,可以支持不同的调用形式,进而可能产生不同的行为。

特别地,如果你能充分区分函数的定义(数据)和函数的声明(变量),同时借鉴一般数据“赋值给变量并通过变量去使用”等价于直接使用它,例如:

var s = 'Hello World!';
console.log(s.length);
// 也可以如下:
console.log('Hello World!'.length); // 不通过变量而直接使用

 那么,对于函数来说,你同样也可以不经过赋值给变量而直接使用它:

(function(){
    console.log('Hello World!');
})();

// 等价于如下:
var f = function(){
    console.log('Hello World!');
};
f()

当然,无论是不是函数型的数据,如果你没有将其赋值给任何变量而是直接使用它,那么它只能被使用一次(因为它没有变量名字,你无法再一次“召唤”它)。

函数的返回

return语句的写法和c/java基本一致。上文已经提到,函数不需要声明和定义返回值类型,只需要直接返回数据即可。

略有不同的是,如果return不返回一个值,在c和java中会以void来表示这个值,而且void并不是一个具体的数据,也就是无法被一个变量所指代。但在javascript中,如果return不显式地返回一个值,则函数仍然会“固执”地返回一个undefined,如下:

var f = function(){
  return; // 不显式地返回任何数据,此行写或不写是等价的
};
var result = f(); // 在c/java中这是非法的,无法把void赋值给任何变量,也无法直接打印
console.log(result); // undefined

javascript函数的这个特性,允许你在同一个函数中条件地返回一个值或根本不返回任何值(当然实际上是返回了undefined)。换句话说,在javascript函数中,return;或直接不写return语句的情况下,都会自动返回undefined。

更进一步地理解,实际上并不是自动返回一个undefined,只是函数的返回值作为一个“匿名变量”,它被声明了(虽然没名字,函数有名字,但返回的那个变量没名字),但却没有被return语句赋值,那么它自然就是undefined(参考上一篇:声明但未显式赋值的变量,其默认值是undefined)。

总结

1、要把函数看成一种数据定义,函数的返回值即是数据的值,函数名既是变量名,var f = function(i){return i+1;}的书写形式能更好地反映其本质;

2、函数变量符合javascript一般变量的所有行为特性,如变量提升等(参考《javascript入门(1):变量和数据》

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值