JavaScript函数浅析

在js中,函数属于较为容易掌握,但使用情况则最为复杂的一种技术。本文仅尝试从如下方面着重阐述一些特点及用法,留待今后update:

 

  •  函数基本特点
  • 几种定义函数的方式及其区别
  • 函数的几种调用方式
  • JavaScript匿名函数

 

函数基本特点:

 1、 函数属于对象类型的一种(ECMAScript中有5中简单类型Undefined、Null、Boolean、Number和String,还有1种复杂类型Object),并且是标准内置类型Function的实例

ECMA-262 写道
function:
member of the Object type that is an instance of the standard built-in Function constructor and that may be invoked as a subroutine.
function demo() {
}
alert(typeof demo);//function,注意,不是object

 2、函数在定义的时候,参数与返回值均为可选。

  • 函数的参数在内部使用一个数组(arguments)来表示,在函数体内可通过arguments[index]来获取指定参数
  • 当没有指定返回值时,将自动返回undefined

3、在js中,函数没有重载,当定义了2个名字相同的函数,则该函数名属于后定义者(或简称覆盖)

 

函数的定义方式

大致分为如下3种:

//1.使用函数声明语法
function demo1(){}

//2.使用函数表达式
var demo2=function(){};//注意不要省略分号,因为有些js引擎实现必须通过分号来判断表达式结尾

//3.使用Function构造函数
var demo3=new Function("m","n","return m+n;");//不推荐

 

 区别:

 

第一种定义方式:常规方式,不赘述

 

第二种定义方式:较为特殊,但基本特点和第一种相似。由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,因此第二种定义方式实质上等价于:首先定义一个匿名函数,然后将其值赋给一个变量。

 

第三种定义方式:在Function构造器中,参数分别为若干个形参和函数的具体实现代码,因为使用这种方式定义的时候存在2次解析(一次解析ECMAScript代码,一次解析传入构造器的字符串)、书写代码可读性不好及脚本注入的问题,故不推荐使用。

 

js解析器在向环境中加载数据时,对前2种方式并非完全一样。

解析器会首先读取函数声明,并使其在执行任何代码之前可访问;而函数表达式,则必须等到解析器执行到他所在的代码行才会真正被解释执行:

alert(demo1(3,4));
function demo1(m,n){
    return m+n;
}

这段代码运行没问题,最终答案为:弹出“7”

 

alert(demo2(3,4));
var demo2=function(m,n){
    return m+n;
};

这段代码在执行期间会导致错误,因为在执行到函数所在语句之前,变量demo2不会保存对函数的引用

 

除开这一点区别之外,函数声明与函数表达式的语法其实是等效的。

 

 函数的几种调用方式:

1、常规方式,不赘述

2、apply

 

function add(n1, n2) {
	return n1 + n2;
}
//param1:在其中运行函数的作用域
//param2:Array的实例
alert(add.apply(this, [ 1, 2 ]));//注意,不能去掉中括号
alert(add.apply(window, [ 1, 2 ]));

 3、call

 

function add(n1, n2) {
	return n1 + n2;
}
//param1:在其中运行函数的作用域
//param2:可变参数,必须逐个罗列
alert(add.call(this,  1, 2 ));
alert(add.call(window,  1, 2 ));

  基本上这2种调用方式的区别就在于第二个参数,apply必须传入一个数组的实例,而call则类是java中的可变参数,必须逐个罗列

 

apply和call在使用场景上,主要是为了扩展函数赖以运行的作用域,而这一点,常规调用方式难以做到

 

var gender = "female";
var obj = {
	gender : "male"
};
function demo() {
	alert(this.gender);
}
demo(this);//female
demo.call(window);//同上
demo.call(obj);//male

 使用call与apply,实际上做到了:解除了函数调用者与函数实现的耦合关系。或者说apply和call用起来有点像java反射当中method.invoke(obj,args)

你可能感兴趣的:(JavaScript,脚本)