JS中的函数

文章详细介绍了JavaScript中函数的定义方式,包括关键字function、表达式定义及Function构造器。还讨论了自调用函数、箭头函数的语法特点。重点阐述了函数提升、函数作为对象的属性和方法,特别是闭包的概念,以及如何利用闭包保护和管理私有变量。
摘要由CSDN通过智能技术生成

学习菜鸟教程JS函数,写下这篇笔记。

目录

一.JS函数定义的三种方式

1.使用关键字function定义函数

2.通过一个表达式定义函数

3. 函数构造器Function()定义函数(不常用)

 二.自调用函数

三.箭头函数

四.函数提升(Hoisting)

五.函数是对象

六.函数参数

七.函数调用的四种类型

1.函数直接调用(未被对象调用)

全局对象

2.函数作为方法调用

3.使用构造函数调用函数

4.函数作为函数方法调用

八.闭包

内嵌函数


一.JS函数定义的三种方式

1.使用关键字function定义函数

function myfunction(a,b){
    return a*b;
}

2.通过一个表达式定义函数

var x = function(a,b){return a*b};
var y = x(3,4);
//y的结果为12

该中方法中的函数被称为匿名函数 ,没有函数名称,通过使用变量来调用。

3. 函数构造器Function()定义函数(不常用

var myFunction = new Function("a","b","return a*b");
var x = myFunction(3,4);
//x结果为12

 二.自调用函数

(function myFunction(){
    var x = "Hello!";    //实际上该函数是一个匿名自我调用的函数
})();                  

//通过在函数表达式后添加(),使得其成为自调用函数

//当代码执行到自调用函数时,自调用函数将会直接执行,不
//再需要调用函数的方法等操作,与普通代码块无异。


三.箭头函数

箭头表达式的语法比普通函数表达式更简洁。

ES6新增的箭头函数。

//多参数类型
(x,y,z)=>{return x*y*z};
//单参数类型
x=>{return x};
//无参数类型
()=>{return "hello!"}; 

注:

1.我们在使用箭头函数时,箭头函数会默认关键字this绑定外层this的值,因此,箭头函数中this的值与箭头函数外层this值是相等的。

2.箭头函数不能提升,需要在使用前完成定义。

3.使用const比使用var更安全,因为函数表达式始终是一个常量。

四.函数提升(Hoisting)

提升(Hoisting)是JS默认将当前代码块的作用域提升到前面的行为。

提升(Hoisting)应用在变量和函数的声明。

myFunction(5);

function myFunction(y){     
    return y;
}
//不会报错,y的值为5

五.函数是对象

在JS中使用操作符typeof判断函数类型将会返回“function”,但是在JS中也可以将函数看做为一个对象。因为JS函数具有属性方法

1.arguments.length属性会返回函数调用过程中接收到的参数个数。

function myFunction(a,b){
    return arguments.length;
}
//返回2

2.toString()方法将函数作为一个字符串返回。

function myFunction(a,b){
    return a*b;
}
var x = myFunction.toString();
//x的值为"return a*b"

 arguments对象

JS函数中有一个内置的arguments对象,arguments对象包含了函数参数的数组。

//返回最大值的函数
function myFunctin(){
    var i,max = arguments[0];
    if(arguments.length < 2) return max;
    for(i = 0; i < arguments.length; i++){
        if(arguments[i] > max){
            max = arguments[i];
        }
    }
     return max;
}

六.函数参数

JS中的函数参数分为函数显式参数隐式参数

显式参数在函数定义时列出。

隐式参数是函数调用时传递给函数真正的值。

function myFunction(a,b){
    return a*b;                //a,b为显式参数
}                              //x,y为隐式参数
var x=1,y=2;
myFunction(x,y);

参数规则

1.JS函数定义显式参数时没有指定数据类型。

2.JS函数对隐式参数没有进行类型检测。

3.JS函数对隐式参数的个数没有进行检测。

默认参数

在ES5中,如果在调用函数时,未定义隐式参数,则参数会默认设置为:undefined

function myFunction(x,y){
    y = y||0;
    return x*y;
}
myFunction(3);
//返回的值为0,y为undefined或null;

但在一般情况下,都会为参数设置一个默认值(初始值)。

function myFunction(x){
    if(x === undefined){
        x = 0;
    }
}

在ES6下,函数会判断函数参数是否有默认值。

function myFunction(x,y = 10){
    return x + y;
}
myFunction(0,2);  //返回2
myFunction(5);    //返回15

注:==与===的区别:

使用==时,如果value1与value2的数据类型不同,会将两者转化为相同的数据类型后再进行值的比较,值相同则true,反之则false。

使用===时,表示在严格模式"use strict"下的相等,如果value1与value2的类型不相同,则false,在数据类型相等且值相等的情况下,则为true。

七.函数调用的四种类型

函数调用类型的不同与关键字this有一定联系,在一般情况下,this会指向函数执行时当前的对象。

1.函数直接调用(未被对象调用)

function myFunction(x,y){
    return x*y;
}
myFunction(2,10);
//结果为20;

该函数不属于任何对象。但在JS中它始终是默认全局对象的函数。

在HTML中默认的全局对象是HTML页面本身,所以它是HTML页面对象的函数。

在浏览器页面中的全局对象是浏览器窗口(window对象)。因此该函数会自动成为window对象的函数。

即myFunction(2,10)和window.myFunction(2,10)是等同的。

注:由于全局变量,方法或函数容易造成命名冲突,产生bug,因此window.myFunction(2,10)不被推荐使用。

全局对象

在函数没有被对象调用时,this的值会自动变为全局对象。

在web浏览器中,全局对象是浏览器窗口(window对象)。

function myFunction() {
    return this;
}
myFunction();                // 返回 window 对象

2.函数作为方法调用

在JS中,匿名函数常作为对象的一个方法。

var myObject = {
    firstName:"John",            //两个属性firstName,lastName
    lastName: "Doe",             //一个方法fullName
    fullName: function () {
        return this.firstName + " " + this.lastName;
    }
}
myObject.fullName();         // 返回 "John Doe"

 fullName方法是一个函数,函数属于myObject对象,这里的this指向myObject对象,所以this为Object对象。

3.使用构造函数调用函数

//构造函数:
function myFunction(arg1, arg2) {
	this.firstName = arg1;
    this.lastName  = arg2;
    return this;
}
var x = new myFunction("John","Doe");
x.firstName;   //x.firstName的值为John
document.write(x);   //输出 object 对象

函数在调用前使用了关键字new,则是调用了构造函数。

前面提到在JS中函数是对象,这里可以理解为新建了一个myFunction类型的x对象。

构造函数的调用会创建一个新的对象,该对象会继承构造函数的属性和方法。

注:构造函数中关键字this没有任何指向的对象,在函数调用实例化对象时,this指向了x对象。

4.函数作为函数方法调用

在JS中,函数也是对象,有属性和方法。

call()apply()是函数的两个方法。两个方法在调用函数时,第一个参数必须是对象本身。

//call()方法
function myFunction(a, b) {
    return a * b;
}
myObject = myFunction.call(myObject, 10, 2);     // 返回 20

//apply()方法,传入数组
function myFunction(a, b) {
    return a * b;
}
myArray = [10, 2];
myObject = myFunction.apply(myObject, myArray);  // 返回 20

在JS严格模式(strict mode)下,在使用这两种方法时,第一个参数会变为this的值(如:window,object);在非严格模式下,如果第一个参数的值为null或undefined,this的值将自动使用全局对象替代。

八.闭包

在JS中,全局变量与局部变量常存在。

全局变量可以用于页面上的所有脚本。

函数内部声明的变量则是局部变量,局部变量只能作用于定义它的函数,对于脚本和其他函数是不可用的。

注:变量声明时如果不使用 var 关键字,那么它就是一个全局变量,即便它在函数内定义。

现存在一个计数器困境。

使用全局变量设置计数器递增。

var a = 0;
function add(){
    return a += 1;
}
add();    //1
add();    //2
add();    //3

计数器确实在递增,但由于a是全局变量,页面的所有脚本都可以改动它,那么计数器将毫无意义。

使用局部变量设置计数器递增。

function add() {
    var a = 0;
    return a += 1;
}
 
add();    //1
add();    //1
add();    //1

毫无疑问,使用局部变量设置计数器递增也是失败的。

内嵌函数

在JS中,所有函数都能够访问它们上一层的作用域。也就是说内嵌函数可以访问上一层函数的变量。

function add1(){
    var a = 0;
    function add2() {a += 1;}
    add2();
    return a;    //a为1
}
add1();    //1
add1();    //1
add1();    //1

这样就完美解决了全局计数器中所有脚本会改变变量a的问题。

看到这儿,可能存在这样的疑问:局部计数器出现的问题与内嵌计数器出现的问题不是一样的吗?其实,内嵌计数器优化了局部计数器中的问题。虽然两者结果都只能是1,但是只要让内嵌计数器中的变量a只执行一次就行了。

这里需要用到前面提到的自调用函数,自调用函数会自动执行,且执行一次。

var add = (function(){
    var a = 0;
    return function() {return a += 1;}
})();

add();        //1
add();        //2
add();        //3

自调用函数执行后,a==0,返回了一个方法;即var add = function(){return a +=1;},这是函数定义类型中的第二类:通过一个表达式定义函数。然后直接调用函数add(),即可实现自增。

这个就是闭包,其中变量a可称为私有变量。计数器受匿名函数的作用域保护,只能通过调用add函数修改。

闭包是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不受外界干扰。直观的说就是形成一个不销毁的栈环境。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值