JS之Function 类型

1 Function

说起来 ECMAScript 中什么最有意思,我想那莫过于函数了——而有意思的根源,则在于函数实际上是对象。每个函数都是 Function 类型的实例,而且都与其他引用类型一样具有属性和方法。由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。函数通常是使用函数声明语法定义的,如下面的例子所示

function sum (num1, num2) { 
	return num1 + num2; 
} 
var sum = function(num1, num2){ 
	return num1 + num2; 
}; 

2 没有重载

在js中函数没有重载

function addSomeNumber(num){ 
	return num + 100; 
} 
function addSomeNumber(num) { 
	return num + 200; 
} 
var result = addSomeNumber(100); //300 

上面的代码相当于一下代码

var addSomeNumber = function (num){ 
	return num + 100; 
}; 
addSomeNumber = function (num) { 
	return num + 200; 
}; 
var result = addSomeNumber(100); //300 

3 函数声明与函数表达式

解析器在向执行环境中加载数据时,对函数声明和函数表达式并非一视同仁。解析器会率先读取函数声明,并使其在执行
任何代码之前可用(可以访问);至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解释执行。

alert(sum(10,10)); 
function sum(num1, num2){ 
	return num1 + num2; 
} 

以上代码完全可以正常运行。因为在代码开始执行之前,解析器就已经通过一个名为函数声明提升(function declaration hoisting)的过程,读取并将函数声明添加到执行环境中。对代码求值时,JavaScript引擎在第一遍会声明函数并将它们放到源代码树的顶部。所以,即使声明函数的代码在调用它的代码后面,JavaScript 引擎也能把函数声明提升到顶部。但是不能像下面这样定义:

alert(sum(10,10)); 
var sum = function(num1, num2){ 
	return num1 + num2; 
}; 

4 函数内部属性

在函数内部,有两个特殊的对象:arguments 和 this。其中,arguments 它是一个类数组对象,包含着传入函数中的所有参数。虽然 arguments 的主要用途是保存函数参数,但这个对象还有一个名叫 callee 的属性,该属性是一个指针,指向拥有这个 arguments 对象的函数。请看下面这个非常经典的阶乘函数

function factorial(num){ 
 if (num <=1) { 
	 return 1; 
 } else { 
	 return num * factorial(num-1) 
 } 
} 
function factorial(num){ 
 if (num <=1) { 
 	return 1; 
 } else { 
 	return num * arguments.callee(num-1) 
 } 
} 
  • this

函数内部的另一个特殊对象是 this,其行为与 Java 和 C#中的 this 大致类似。换句话说,this引用的是函数据以执行的环境对象——或者也可以说是 this 值(当在网页的全局作用域中调用函数时,this 对象引用的就是 window)。

window.color = "red"; 
var o = { color: "blue" }; 
function sayColor(){ 
 alert(this.color); 
} 
sayColor(); //"red" 
o.sayColor = sayColor; 
o.sayColor(); //"blue"

5 函数属性和方法

ECMAScript 中的函数是对象,因此函数也有属性和方法。每个函数都包含两个属性:length 和 prototype。

  • length

其中,`length 属性表示函数希望接收的命名参数的个数。·

function sayName(name){ 
 alert(name); 
} 
function sum(num1, num2){ 
 return num1 + num2; 
} 
function sayHi(){ 
 alert("hi"); 
} 
alert(sayName.length); //1 
alert(sum.length); //2 
alert(sayHi.length); //0 
  • prototype

在 ECMAScript 核心所定义的全部属性中,最耐人寻味的就要数 prototype 属性了。对于ECMAScript 中的引用类型而言,prototype 是保存它们所有实例方法的真正所在。换句话说,诸如toString()和 valueOf()等方法实际上都保存在 prototype 名下,只不过是通过各自对象的实例访问罢了。

6 apply()和 call()

  • 它们各自的定义

apply:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.apply(A, arguments);即A对象应用B对象的方法。
call:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.call(A, args1,args2);即A对象调用B对象的方法。

  • 它们的共同之处

都“可以用来代替另一个对象调用一个方法,将一个函数的对象上下文从初始的上下文改变为由thisObj指定的新对象”。

  • 它们的不同之处

apply:最多只能有两个参数——新this对象和一个数组argArray。如果给该方法传递多个参数,则把参数都写进这个数组里面,当然,即使只有一个参数,也要写进数组里。如果argArray不是一个有效的数组或arguments对象,那么将导致一个TypeError。如果没有提供argArray和thisObj任何一个参数,那么Global对象将被用作thisObj,并且无法被传递任何参数。

call:它可以接受多个参数,第一个参数与apply一样,后面则是一串参数列表。这个方法主要用在js对象各方法相互调用的时候,使当前this实例指针保持一致,或者在特殊情况下需要改变this指针。如果没有提供thisObj参数,那么 Global 对象被用作thisObj。

实际上,apply和call的功能是一样的,只是传入的参数列表形式不同。

function sum(num1, num2){ 
 return num1 + num2; 
} 
function callSum1(num1, num2){ 
 return sum.apply(this, arguments); // 传入 arguments 对象
} 
function callSum2(num1, num2){ 
 return sum.apply(this, [num1, num2]); // 传入数组
} 
alert(callSum1(10,10)); //20 
alert(callSum2(10,10)); //20 
function sum(num1, num2){ 
 return num1 + num2; 
} 
function callSum(num1, num2){ 
 return sum.call(this, num1, num2); 
} 
alert(callSum(10,10)); //20

7 bind()

这个方法会创建一个函数的实例,其 this 值会被绑定到传给 bind()函数的值。例如:

window.color = "red"; 
var o = { color: "blue" }; 
function sayColor(){ 
 alert(this.color); 
} 
var objectSayColor = sayColor.bind(o); 
objectSayColor(); //blue 

猜你喜欢

转载自blog.csdn.net/qq_27870421/article/details/89483995