JS复习5----浅谈JS函数

JS函数

  1. JS函数定义

a. 使用关键字function声明定义函数
b. 函数声明后不会立即执行,会在我们需要的时候自己调用
c. JS函数可以通过一个表达式定义,函数表达式可以存储在一个变量中(小心这句话了啊):

var x = function(a,b) { return a*b;} //声明一个函数并存储在变量x中
x(3,4);  //调用函数

d. Function()构造函数
var myFunction = new Function(“a”,“b”,“return a*b”);
少用啊,最好别用,在JS中尽量避免使用new关键字,代码也怪长的,不是吗
e. 函数存在提升(先使用后声明),但是使用表达式定义函数时无法提升
f. 自调用函数

(function() {
var x = "Hello";
})();  //我将调用我自己,不能自调用声明的函数

g. 函数可以作为一个值使用
var x = myFunction(3,4);
h. 函数可以作为一个表达式使用
var x = myFunction(3,4)*2;
i. 函数是对象
当你使用typeof打印一个函数时,会返回function,但是将函数描述成一个对象更为准确,因为JS函数有属性和方法
arguments.length属性返回函数调用过程中接收到的参数个数
toString()方法将函数作为一个字符串返回
myFunction.toString();
j.箭头函数(详细的会在后续的关于Es6的文章中阐述)
不存在提升,默认绑定外层的this

  1. JS函数参数

a. 函数显式参数(Parameters)和隐式参数(Arguments)
函数显式参数在函数定义时列出
函数隐式参数在函数调用时传递给函数真正的值
b. 参数规则
JS函数定义显式参数时没有指定数据类型
JS函数对隐式参数没有进行类型检测
JS函数对隐式参数的个数没有进行检测
c. 默认参数
ES5中如果函数调用时未提供隐式参数,参数会默认设置为:undefined
d. ES6函数可以自带参数
function myFunction(x,y = 10){}
e. arguments对象
函数的内置对象,里面包含了函数调用的参数数组
f. 通过值传递参数
在函数中调用的参数是函数的隐式参数,隐式参数通过值传递,函数仅仅只是获取值,隐式参数的改变在函数外是不可见的
g.通过对象传递参数
在JS中,可以引用对象的值,修改对象属性在函数外是可见的

  1. JS函数调用

    JS函数有4种调用方式,每种方式的不同在于this的初始化,this一般而言,指向函数执行时的当前对象
    a. 作为一个函数调用

    function myFunction(a,b) { return a * b;};
    myFunction(3,4);  //相当于window.myFunction(),此时this指向window对象
    

    这是调用JS函数常用的方法,但不是良好的编程习惯,全局变量、方法、或者函数容易造成命名冲突的bug
    b. 函数作为方法调用
    作为对象的方法调用,this指向对象本身
    c. 使用构造函数调用函数
    如果函数调用前使用了new关键字,则是调用了构造函数,这看起来就像创建新的函数,但实际上是重创的对象

    function myFunction(a,b) { return a * b;};
    var x = new myFunction(3,4); //构造函数的调用会创建一个新的对象,新对象会继承构造函数的属性和方法
    

    在构造函数中this没有任何的值,this的值在函数调用实例化对象(new Object)时创建
    d. 作为函数方法调用函数
    call和apply是预定义的函数方法,两个方法可用于调用函数,两个方法的第一个参数必须是对象本身

    function myFunction(a,b) { return a * b;}
    myObject1 = myFunction.call(myObject1,10,2);
    myArray = [10,2];
    myObject2 = myFunction.apply(myObject2,myArray);
    //两者的区别在于,apply传入的第二个参数是一个多个参数组合的数组
    

    通过call或apply方法你可以设置this的值,且作为已存在对象的新方法调用

  2. JS闭包

关于JS闭包,我们得看JS的一个问题,计数器困境:设想下如果你想统计一些数值,且该计数器在所有函数中都是可用的
我们最容易想到的是使用全局变量,比如:

var counter = 0;
function add() {
   return counter += 1;
   }
add();
add();
add();  //计数器现在为3

计数器数值在执行 add() 函数时发生变化。
但问题来了,页面上的任何脚本都能改变计数器,即使没有调用函数,因为它是全局变量嘛,那这就没什么意义了

那我们尝试将变量定义在函数内部

function add() {
    var counter = 0;
    return counter += 1;
}
add();
add();
add();   //抱歉,结果都是1,因为每一次都要执行一次初始化

那有没有让counter只初始化一次,又定义在函数内部的解决办法?JS闭包就可以,我们看下列代码:

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

代码解析: 这里定义了一个自调用函数,函数执行之后初始化counter为0,并返回一个匿名函数存储到变量add中,由于变量counter一直被内嵌的匿名函数引用着,所以不会被回收,多次执行add,将里面的counter修改为3
闭包是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不受外界干扰,直观的说就是形成一个不销毁的栈环境
简单的说,闭包就是一个函数引用另一个函数的变量,因为变量被引用着所以不会被回收,因此可以用来封装一个私有变量,但是不必要的闭包只会增加内存消耗,或者说闭包就是子函数可以使用父函数的局部变量,还有父函数的参数
好了,我的分享就到这里了,谢谢大家

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值