零基础快速掌握JavaScript(4)函数简介及创建方式、函数的本质与内部函数、函数应用及闭包

发布时间:2022-07-05 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了零基础快速掌握JavaScript(4)函数简介及创建方式、函数的本质与内部函数、函数应用及闭包脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

 

零基础快速掌握JavaScript(4)函数简介及创建方式、函数的本质与内部函数、函数应用及闭包

目录

一.函数介绍

二.函数的作用

三.如何创建函数

1.创建函数的两种方式

2.两种方式的区别

四.函数内部属性

1.arguments   ☆☆☆

2.this

3.IIFE函数

4.作用域

五.函数调用

六.函数本质

七.函数的应用

1.函数当作参数应用

2.函数作为返回值的情况

八.闭包

1.闭包创建方式

2.闭包的特点

3.闭包的优缺点


一.函数介绍

      函数允许我们封装一系列代码来完成特定任务。当想要完成某一任务时,只需要调用相应的代  码即可。方法(;method)一般为定义在对象中的函数。浏览器为我们提供了很多内置方法,我们不需要编写代码,只需要调用方法即可完成特定功能。

二.函数的作用

功能的封装,直接调用,代码复用率提高(代码复用率是指相同代码被复用的概率,在某种程度上,代码复用率越高,代码越容易阅读,维护成本越低)

构建对象的模板(构造函数

三.如何创建函数

1.创建函数的两种方式

//自定义函数

//方式一 函数声明
function test(){//function关键词  test函数名  ()参赛部分
	//功能体
	console.LOG(1)
}

//方式二 函数表达式 使用变量声明
VAR t1 = function () {
	console.log(2)
}
test();//1
t1();//2

2.两种方式的区别

变量提升

//两种方式的区别F1a;1变量提升
var c = 2;
function cook(a='番茄',b='鸡蛋'){//ab为形参 参数可以有默认值
//写参数时尽量把没有默认值的放在前面,这样在有值调用时会优先把值传给没有默认值的参数
//if(tyPEof a==undefined){}可以用判断语句来止出现undefined的bug
	var c = 1;
	console.log(c);//1 
//函数中会优先从局部寻找变量值,当局部没有时才会在全局寻找,都没有时就会报错
    console.log(a+'炒'+b);
}
cook();//番茄炒鸡蛋
cook('萝卜');//萝卜炒鸡蛋


var c = 2;
function cook(a='番茄',b='鸡蛋'){
	console.log(c);//undefined 
//在函数中声明变量,变量名会被提升到局部顶端
//所以这时局部有变量c,就不会在全局寻找,所以值为undefined
	var c = 1;
    console.log(a+'炒'+b);
}


function cook(a='番茄',b='鸡蛋'){
	var c = 1;
	var res = a+'炒'+b;
//return设置函数返回值
//若函数在执行完毕后,需要一个结果,这个结果可以通过某个变量接收,那么就可以设置return,
//若我们只是想要执行一段逻辑,这段逻辑执行完毕即可,那就不需要设置return,
	return res;//返回只有一个,并且返回后所有代码都无效了	
	console.log()//无效
}
var res = cook('apple');//res接收的就是函数的返回值
console.log(res);//apple炒鸡蛋

四.函数内部属性

1.arguments   ☆☆☆

arguments是一个类数组对象,包含传入函数的所有参数

//函数内部属性
//arguments 是一个类数组对象,包含传入函数的所有参数
//类数组对象不是数组,可以当做数组使用,但不能使用数组的方法
//内部的下标跟数组相似,还需要有length,如果一个对象包含这2个特征,才被称为类数组对象
function add(a,b){
	console.log(arguments);
}
add(1,2);//[Arguments] { '0': 1, '1': 2 }

function add(a,b){
	console.log(arguments.length);
}
add(1,2);//2

function add(a,b){
	console.log(arguments[0]);
}
add(1,2);//1

//在arguments中有一个属性 callee- 执行拥有该arguments的函数
//递归函数 在函数体内部调用自身 传入一个数10实现 10*9*8...*2*1
//使用递归函数时需要在某个时刻跳出循环
function digui(num) {
	if (num<=1) {
		return 1;
	}else
	return num * arguments.callee(num-1)
}
var res = digui(10);
console.log(res);

2.this

函数内部有this属性,指向函数所在环境,

//函数的内部有this属性,指向函数所在环境, 
var a = 2;//不写var 就会存在global中
function add() {
    console.log(this.a)//从Window中找a
}//this指向函数所在环境,这个函数在外部,即为全局
//当在浏览器中时指向window,当在node中时指向global
add();

var a = 2;
function add() {
    console.log(this.a);//2
//函数定义在全局 从window中找a,不会从函数内部找,所以与下面这个新var的a没有关系
//当去掉this后console.log(a),这时会提升undefined,
//因为此时没有指向,所以会优先从内部寻找,就会发生变量提升,与上面的a=2就没有关系了
    var a = 1;
    console.log(a);//1
}
add();

var obj = {
    a:3,
    add(){//函数在对象内部定义,所以this指向该对象而非window或另一个函数
        console.log(this.a);//3
    }
}

总结:函数或方法定义在全局,则可以在函数内部通过this调用这个函数或者在外部的方法 函数定义在对象内部,则可以在函数内通过this调用这个对象的内部属性或方法

3.IIFE函数

//IIFE函数 在js ES5中的块级作用域(模拟的块级作用域)
//块级作用域是为了隔离作用域,防止污染全局
//es6块级作用域写法
var a = 1; 
console.log(a);
{
    var a = 2;
    console.log(a);//相互独立,各打印各的
}
//es5写法
function test() {
    var a = 3;
    console.log(a);
}
test();//每次块级作用域声明完需要手动执行,而es6中是直接执行

(function () {//这个函数在声明后会立即调用
    var a = 4;
    console.log(a);
})()

4.作用域

函数作用域:函数内部声明的变量,在函数外部不能访问

全局作用域:函数外部声明的变量,在函数内部可以访问。

当函数嵌套,在这个时候,内部函数与外部函数的这个变量就组成了闭包。

    在js中函数内部不存在块级作用域

五.函数调用

改变函数执行环境的三种方法:call()、apply()、bind()()

//如何改变函数的执行环境

name = 'xiaoming'
function sayName(a,b) {
    console.log(this.name);
    console.log(a+b);
}
var obj1 = {
    name:'zhangsan',
}
var obj2 = {
    name:'lis',
}
sayName();//xioaming  NaN(非数值类型) nan是因为没有给ab传值
sayName.call(obj1);//将sayname方法的this指向变为obj1
sayName.call(obj2);//lis
sayName.apply(obj1);//zhangsan
sayName.bind(obj1)();//zhangsan

sayName(1,2);
sayName.call(obj1,1,2);
sayName.apply(obj1,[1,2]);
sayName.bind(obj1)(1,2);//返回的是一个方法

六.函数本质

函数本质上也是一种对象,拥有属性和方法

函数在内存中的表现形式:

函数当做特殊的对象,栈中保存函数名,堆中有两块区域:函数本身、函数原型,两块区域互相指向,你中有我我中有你,类似于Java的方法区。原型主要用在构造函数中

函数本质是一个对象,每个函数都有一个原型对象,通过"函数名.PRototype"来访问该原型对象;原型对象中有个属性"constructor"指向函数

prototype:用来进行指向,创建对象时,若想让所创对象有方法,可以让其定义在Prototype上

//函数的剖析(构造器函数)
function Animal(name,age) {
    this.name=name;
    this.age=age;
}
Animal.prototype.sayHello=function () {
//原型属性的功能:可以在原型属性中定义某些方法和属性,
//从而让创建的对象拥有这个方法或属性,如下面的对象xb
    console.log(hello);
}
var d1 = new Animal('xb',2);
console.dir(Animal);
d1.sayHello();//hello

零基础快速掌握JavaScript(4)函数简介及创建方式、函数的本质与内部函数、函数应用及闭包

零基础快速掌握JavaScript(4)函数简介及创建方式、函数的本质与内部函数、函数应用及闭包

 七.函数的应用

1.函数当作参数应用

函数做参数应用由于函数名本身就是变量,所以函数可以当做值来使用(参数,返回值)

使用场景:定时器、Ajax的使用、数组遍历

var arr = [1,2,3,4,5];
arr.foreach(function (v) {//v代表循环打印的一项
//在foreach函数内部要放一个函数作为参数使用,即回调函数
    console.log(v);//1  2  3  4  5
})
//定时器
//bom方法 在node中无法测试
setTimeout(function () {
    console.log('可以抢票了');
},2000);//2000毫秒=2秒 两秒后开始打印

2.函数作为返回值的情况

function add(a,b) {
//在这里可以返回函数、变量、对象
    return function () {
        return a+b;
    }
}
var res=add(1,2);//返回了function
console.log(res());//3

八.闭包

闭包简单说就是创建一个函数,这个函数的函数体内部有一个变量,为了访问这个变量又在函数体内部创建了一个函数,以此来访问,即指有权访问另一个函数作用域中的变量的函数。

1.闭包创建方式

闭包的创建方式,就是在一个函数内部创建另外一个函数。

//闭包
//经典例子
function getName() {
    var num=0;
    return function () {
        return num;
    }
}
//console.log(num);//报错
//通常情况下我们无法直接访问局部变量,而通过这个例子可以实现外部访问函数内部变量的操作
var num = getName();
console.log(num());//0

2.闭包的特点

-函数的内部函数;-函数的内部引用外部的变量;-闭包不会被垃圾回收机制回收

function getNum() {
    var num = 0;
        return function () {
            var n = 0;
            console.log(++num);
//num引用了外部的num所以不会被销毁,所以逐次增加
            console.log(++n);
//n在执行完被销毁,因为没有被引用,所以一直是1
        }
    }
var res = getNum();
//保持引用关系 res引用num,num又被内部引用,所以达到闭包效果不被销毁
res();// 1  1
res();// 2  1
res();// 3  1
getNum()();//这样写getNum将会被销毁,所以num一直为0

3.闭包的优缺点

优点:闭包可以调应函数内部变量,所以在封装有优势,若在实例中使用闭包,因为闭包可以持续拥有一个变量,这样就可以实现变量的累加、缓存等。

缺点闭包只能取得包含函数中任何变量的最后一个值。

          若闭包的变量不使用了,则因为其特殊的机制不被回收,从而造成内存损耗

解决方法:手动赋值为null

//闭包实例
for (var i = 1; i <=10; i++) {
    setTimeout(function () {
    console.log(i);
    },1000)
}// 11  11  11  11...
//因为执行代码时,同步不会等异步,所以外部for循环先执行完毕,
//然后内部异步函数才开始执行,所以一直是11
//解决方法一: IIEF创建局部块
for(var j = 1; j <=10; j++){
    (function (j) {//接受局部块变量
        setTimeout(function () {
            console.log(j);
    })//每次执行for循环都会执行一个局部块
    })(j)//传入局部块变量
}
//0 1 2 3 4...10

//解决方法二: 使用let
for (let i = 0; i <=10; i++) {
    setTimeout(function () {
        console.log(i);
},1000);
}
//0 1 2 3 4...10
//进阶版实例
function getNum(num) {
    var res = [];
    for (var i = 0; i < num; i++) {
        res[i] = (function(i){//把i的值赋给数组res中下标为i的元素
            return function(){
                console.log(i);//从零开始输出i的值
            }
        })(i)
    }
    return res;//返回了包含多个函数的数组
}
var arr = getNum(3)
arr[0]();//0
arr[1]();//1
arr[2]();//2

脚本宝典总结

以上是脚本宝典为你收集整理的零基础快速掌握JavaScript(4)函数简介及创建方式、函数的本质与内部函数、函数应用及闭包全部内容,希望文章能够帮你解决零基础快速掌握JavaScript(4)函数简介及创建方式、函数的本质与内部函数、函数应用及闭包所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。