【javascript基础】2、函数

原文:【javascript基础】2、函数

前言


我在上一篇【javascript基础】基本概念中介绍了javascript的一些基本概念,多谢大家的阅读和意见,自己写的东西可以被大家阅读,真心高兴,刚开始发布的时候我一直盯着阅读人数,虽然知道大家可能就是点开一下而已,但是还是给我一些继续写下去的信心。那今天写一些关于javascript函数的一些知识,帮助大家熟悉或者复习一些函数的基本知识。

PS:最近jQuery源码交流群( 239147101)加了不少热新人,希望大家还是以学习为主,尽量少灌水,给大家一个好的提升自己的环境。

函数

函数在任何一种编程语言中都是一个很重要的结构或者组成部分,编程中的复杂结构和功能都会有函数的参与。javascript中的函数是一个对象,函数对象时Function类型的实例,由于Function类型是一个引用类型,那么函数可以拥有自己的方法和属性,同时也因为函数是一个对象,那么函数名是一个指向函数对象的指针,可以被赋值。下面详细介绍函数的各个部分。

创建函数

函数的创建有三种方式,分别为使用Function的构造函数、函数声明、函数表达式,下面分别介绍这三种方法。

Function构造函数

这种方式是直接new出来一个Function
实例,通过使用Function的构造函数进行创建函数。Function构造函数可以接收任意多个参数,但是最后一个参数会被认为是函数体,前面的所以参数被当做被创建出来的函数的参数。

var test = new Function("a","b","return a + b");//参数a和b,函数体return a + b
console.log(test(1,2));//3

我们可以看出比较的麻烦,并且《javascript高级程序设计》也不推荐我们使用这种方式,主要是因为浏览器要解析常规的javascript代码之外,还要解析传入的参数字符串,这个类似eval()的解释,影响性能。

函数表达式

这种方式是创建的常见方式之一,具体请看

var test = function(a,b){
return a + b;
}
console.log(test(1,2));

上面的代码就是创建一个函数,使用test()进行调用。其实,上面的代码是先创建了一个匿名的函数,之后把这个匿名的函数赋值给test变量。每个函数有一个name属性,这个属性不是ECMA标准的一部分,但是许多地方可以使用它。我们可以给上面的函数起一个名字,具体下面代码


//函数的名字newName
var test = function newName(a,b){
return a + b;
}
console.log(test.name);//newName

//匿名函数
var nTest = function (a,b){
return a + b;
}
console.log(nTest.name);//undefined

这个属性在后面详细解释吧。

函数声明

这种方式和C语言中的很类似,这种是最常见的一种创建函数的方法。是通过关键字function直接声明,请看

function test(a,b){
return a + b;
}
console.log(test(1,2));//3
console.log(test.name);//test

区别

以上介绍了三个创建函数的方式,现在介绍三种的区别,确切的说是后两种的区别,因为Function不推荐使用,性能是一大原因。区别就是使用函数声明这种方式会使函数的声明提前,类似前面我们提到的变量申明的提前。也就是说,使用函数申明方式,我们可以将函数的声明放在调用函数代码的后面,因为解析器会在代码执行之前将函数的声明提升,提到源代码树的顶部,而函数表达式方式则会报错,具体请看


//调用函数
console.log(test(1,2));//3
//创建函数(函数申明方式)
function test(a,b){
return a + b;
}
//上面的函数相等于
//创建函数(函数申明方式)
//function test(a,b){
// return a + b;
//}
//console.log(test(1,2));//3

//调用函数
console.log(ntest(1,2));//TypeError: undefined is not a function
//创建函数(函数表达式方式)
var ntest = function (a,b){
return a + b;
}

not重载


javascript语言不像java那些语言有函数重载这一概念,其实函数名就是一个指针,指向一个Function实例的地址,当然只能指向一个函数,当然没有重载的概念了,只有覆盖,后面定义的函数覆盖前面定义的函数,具体请看


function test(a,b){
return a + b;
}
//下面的函数覆盖上面的
function test(a,b){
return a + b + 100;
}

console.log(test(0,0));//100

也就是说如果一个同名的函数表达式和函数申明的函数在一起,无论位置是怎么样的,最后的函数就会是用函数表达式创建的函数,因为函数申明会提升到顶部嘛,看看下面的代码


var test = function (a,b){
return a + b -100;
}

function test(a,b){//会被下面的函数覆盖
return a + b;
}

function test(a,b){//会被函数表达式覆盖
return a + b + 100;
}

console.log(test(0,0));//-100

内部属性


函数的内部有两个重要的对象:arguments和this。

arguments

arguments是一个类似组对象,包含所以传入函数的所有参数, 写程序或者面试中常问的就是如何将arguments转化完成一个数组,请看

Array.prototype.slice.call(arguments);
Array.prototype.slice.call(arguments,0);
Array.prototype.slice.call(arguments,0,arguments.length);
Array.apply(this, arguments); //没用过
Array.apply(null, arguments); //没用过

arguments有一个length属性,表示函数传入参数的个数,还有一个callee属性,这是一个指针,指向拥有这个arguments的函数,这个主要是在函数内部调用自己时使用,也就是递归时使用。看个例子就明白了


function test(count){
console.log("参数:"+arguments[0]+"个数:"+arguments.length);
if(count <= 0){
console.log("递归"+count+" 结束了");
}else{
console.log("递归"+count);
arguments.callee(--count);//调用自己
}
}
test(3);
/*
参数:3个数:1
递归3
参数:2个数:1
递归2
参数:1个数:1
递归1
参数:0个数:1
递归0 结束了
*/

this

javascript中的this和java中的this差不多,this引用的是函数的执行环境,就是this在不同的执行环境中引用的是不同的对象,执行环境这里还没有说到,以后会详细介绍,这里的this也是简单的介绍一下,我以后会整理一些面试题,帮助大家理解。看例子吧,


//全局变量
var color = "red";//相当于window.color = "red"
//定义一个对象
var obj = {color : "blue"};
function pop(color){
alert(this.color);
}
pop();//相当于window.pop();输入"red"
//obj对象增加一个方法,将pop赋值给它
obj.pop = pop;
obj.pop(); //输出"blue"

解释一下,this这个对象是在函数执行时才绑定的,可以说是一个动态的。pop函数是定义在window下的一个函数,也就是全局作用域的一个函数,当直接执行pop函数时,就是在全局作用域下调用pop时。this引用的是window,this.color就是window.color,输出red。当我们把pop这个函数赋值给obj这个对象并且调用pop的时候,this引用的就是obj这个对象,this.color
就是obj.color,输出blue。

函数属性和方法

这里说一下函数的属性和方法,包括length,name,prototype,apply,call这几个。

length

这个属性比较简单,就是表示定义函数时定义的参数的个数,要和arguments.length区分开,arguments.length表示实际输入的参数个数,看例子


function test(a,b){
console.log("输入的参数个数:"+arguments.length);
console.log("定义的参数个数:"+test.length);
}
test();//0,2
test(1);//1,2
test(1,2)//2,2
test(1,2,3)//3,2
//函数的内部我们可以通过arguments[i],取得输入的参数,假如定义一个参数,输入两个参数,那怎么取得第二个参数呢
function testA(c){
console.log("输入的参数个数:"+arguments.length);
console.log("定义的参数个数:"+test.length);
console.log("第二个参数:"+arguments[1]);
}
testA(1,100);2,2,100
//这里可以遍历取得所有的参数,不讲了

name

这个属性在前面提到了一点,这个就是函数的名字,我们在创建函数的时候说了这个属性,这个属性不是标准属性,但是很多地方就使用这个属性,主要也是在递归调用上使用。name属性是只读属性,不能修改它的值。直接看例子


//修改name属性
function test(){
console.log(test.name);
//修改name属性
test.name = "newName";
console.log(test.name);
}
test();//test,test
//函数内部使用name属性,递归调用
function testD(count){
console.log("参数:"+arguments[0]+"个数:"+arguments.length);
if(count <= 0){
console.log("递归"+count+" 结束了");
}else{
console.log("递归"+count);
testD(--count);//调用自己
}
}
testD(3);
/*
参数:3个数:1
递归3
参数:2个数:1
递归2
参数:1个数:1
递归1
参数:0个数:1
递归0 结束了
*/

name属性的使用和arguments.callee()的效果是一样的,只不过arguments.callee()更方便些,当函数名字更改时程序不用更改。

prototype

函数的prototype属性是一个很重要的属性,特别是在自定义引用类型和实现继承时。我们现在这简单的介绍一下它,因为这个属性足以单独写一篇文章。我们可以认为prototype是一个模板,在new
一个对象时候会参照这个模板,将模板里的属性和方法复制给对象,当然你不定义这个模板,这个模板不存在方法和属性。简单例子


function People(name){
this.name = name;
}
//prototype中的属性
People.prototype.home = "jilin";
var hainan = new People("hainan");
console.log(hainan.home);//jilin

先简单介绍到这,后面单独详细说。

call和apply

这两个方法作用是一样的,就是改变this作用域的值,在特定的作用域中调用自己,也就是设置this的指向,不同点在于参数接收方式不同。apply方法需要两个参数,第一个是指定的作用域,就是要把this指向的对象,第二个是参数数组,函数调用需要的参数,这个参数数组也可以是arguments这个伪数组。call的第一个参数也是给this绑定的值,其他的参数个数不定,其他的参数就是函数调用需要的参数,和apply不同,你要一个一个的都列举出来。看例子


function sum(a,b){
return a + b;
}
//arguments参数
function callSum1(a,b){
return sum.apply(this,arguments);
}
//数组参数
function callSum2(a,b){
return sum.apply(this,[a,b]);
}
//列举所有参数
function callSum3(a,b){
return sum.call(this,a,b);
}
console.log(callSum1(1,2));
console.log(callSum2(1,2));
console.log(callSum3(1,2));

上面是传递参数的例子,再看看改变this指向的例子


//全局变量
var color = "red";//相当于window.color = "red"
//定义一个对象
var obj = {color : "blue"};
function pop(color){
alert(this.color);
}
pop();//相当于window.pop();输入"red"
pop.call(this);//red
pop.call(obj);//blue

解释一下,pop.call(this)这句代码改变了this的指向,因为是在全局中调用的函数,this指向window,输出window.color。pop.call(obj)这句代码将this指向了obj,所以输出obj.color。

小结

把函数这部分的基础和大家说了一下,自己讲代码敲了一遍实验了一下,有些东西看着容易懂,写起来还是挺困难的,希望大家也要多写写吧,我一直以为作文就不好,这是难为大家了。要放假了,有点想家了,想吃家里的酸菜了。

【javascript基础】2、函数,布布扣,bubuko.com

时间: 2024-10-12 05:44:12

【javascript基础】2、函数的相关文章

JavaScript 基础回顾——函数

在JavaScript中,函数也是一种数据类型,属于 function 类型,所以使用Function关键字标识函数名.函数可以在大括号内编写代码并且被调用,作为其他函数的参数或者对象的属性值. 1.命名函数的创建和使用 <script type="text/javascript"> function 函数名 (形参列表) { //执行语句 return 返回值; } </script> 2.函数的参数和返回值 与C#,java等语言相比,JavaScript函

JavaScript基础之函数与数组

 函数    函数的基本概念 为完成某一功能的程序指令(语句)的集合,称为函数.有的程序员把函数称为方法,希望大家不要被这两个名词搞晕了. 函数分为:自定义函数.系统函数(经常查看js帮助手册). js自定义函数基本语法: function 函数名(参数列表){ //代码语句 return 值;//有无返回值是可以选择的. } 参数列表:表示函数的输入 函数主体:表示为了实现某一功能代码块 函数可以有返回值,也可以没有 例,    函数.html: <!DOCTYPE html> <ht

javascript基础知识--函数定义

函数声明式 function funname( 参数 ){ ...执行的代码 } 声明式的函数并不会马上执行,需要我们调用才会执行:funname(); * 分号是用来分隔可执行JavaScript语句,由于函数声明不是一个可执行语句,所以不以分号结束. 函数表达式 var x = function( 参数 ){ ...执行的代码块 }; 函数表达式定义的函数,实际上也是一个匿名函数(这个函数没有名字,直接存储在变量中) * 函数表达式结尾是要加分号的,因为它是一个执行语句. Function

JavaScript 基础(五) 函数 变量和作用域

函数定义和调用 定义函数,在JavaScript中,定义函数的方式如下: function abs(x){ if(x >=0){ return x; }else{ return -x; } } 上述abs() 函数的定义如下: function 指出这是一个函数定义; abs 是函数的名称: (x) 括号内列出函数的参数,多个参数以,分隔: {...}之间的代码是函数体,可以包含若干语句,甚至可以没有任何语句. 注意:函数体内部的语句在执行时,一旦执行到return 时,函数就执行完毕,并将结果

JavaScript基础-即时函数(Immediate Functions)

1.即时函数的声明方法 即时函数(Immediate Functions)是一种特殊的JavaScript语法,可以使函数在定义后立即执行:(function () {    alert('watch out!');}()); 下面分几部来理解这种写法: 橙色部分是一个函数表达式: 天蓝色的一对括号代表立即执行它,括号里是执行这个函数需要的参数(这个例子不需要参数): 再用一对括号(就是黑色的这一对)把上面的部分包起来. 黑色这一对括号可以让人明白这个表达式得到的是函数的返回值,而不是函数对象.

JavaScript基础及函数,BOM,DOM的节点及DOM节点操作

使用js的三种方式 1.直接在HTML标签中,使用事件属性,调用js代码: <button onclick="alert('点我呀')">点我啊!<tton> 2.在页面的任意位置,使用script标签 <script type="text/javascript"> alert('哈哈哈') </script> 3.外部:使用script标签 src属性选择外部地址, type属性选择"text/javasc

JavaScript基础之函数和变量作用域

函数:封装一项任务的步骤清单的代码段,再起一个名字 ( js中函数也是一个引用类型的对象,函数名其实也是引用函数对象的普通变量.) 函数对象:内存中专门存储一个函数定义的存储空间 函数定义的存储位置在window之外. 何时使用:一项任务可能反复使用时,就仅需要在函数中封装一次,反复调用函数即可. 如何声明函数: function 函数名([参数1,参数2,...]){ 步骤清单 return 返回值 } 参数:专门接受函数调用时,必要数据的变量 如何使用参数:在函数内,参数变量的使用和普通变量

JavaScript基础CallBack函数

前面提到,函数对象是可以作为参数传递给另一函数的,这时,作为参数的函数如果在内部被执行,那么它就是个回调函数(Callback): function writeCode(callback) { // do something... callback(); // ... } function introduceBugs() { // ... make bugs } writeCode(introduceBugs); 在上面的代码里,introduceBugs就作为writeCode的参数,在wri

javascript基础-js函数

一.创建函数的方式 1)普通方式 function cal( num1, num2 ) { return num1+num2; } 2)使用变量初始化方式 var plus = function(num1, num2) { console.log(num1 + num2); } // 调用 plus(15,20); 3)使用构造函数 //这种方式不推荐使用,这种语法会导致解析两次代码 var box = new Function("num1", "num2", &q

javascript基础 方法 函数 闭包 集合

定义类 ,实例化对象类 ,调用 为类对象增加数据成员 --