03-JavaScript-函数

函数就是将特定功能的代码封装起来,当需要实现特定功能时,直接调用函数实现即可。

一、函数定义和使用

1.1 定义函数
  • 语句式命名函数
function sum(a,b) {return a + b;
}
  • 变量函数表达式
    是一个匿名函数,它没有函数名
let sum = function(a,b) {return a + b;
};
1.2 调用函数

按顺序传入参数

console.log(sum(1,3))
function sum(a,b) {return a + b;
}let sum2 = function(a,b) {return a + b;
};
console.log(sum2(1,3))

函数声明提升:
语句式命名函数存在函数声明提升,函数表达式声明函数函数时,不可以把函数调用写在函数声明前面,因为变量赋值不存在提升。

1.3 arguments
  • 在函数内部起作用,指向当前函数的调用者传入的所有参数,它是一个类似数组的对象
let sum2 = function(a,b) {console.log(arguments)  //[1, 3, 4, 5, callee: ƒ, Symbol(Symbol.iterator): ƒ]console.log(arguments[2]) //4return a + b;
};
sum2(1,3,4,5)
  • arguments…length 获取调用函数实参个数
  • callee 属性,指向拥有这个arguments对象的函数
1.4 rest参数

剩余参数,遵循传入顺序后的,所有参数。rest参数只能写在最后,前面用…标识

let sum = function(a,b,...rest) {console.log(rest) //[4, 5]return a + b;
};
sum2(1,3,4,5)

二、变量作用域与解构赋值

2.1 变量提升

JavaScript的函数定义有个特点,它会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部

2.2 全局作用域

函数之外声明的变量,会成为全局变量,就具有全局作用域

2.3 局部作用域

函数中声明的变量,会成为函数的局部变量,在函数外部不能访问

2.4 作用域链

当前作用域没有定义的变量,会顺着作用域向父作用域找,如果父级也没有找到,再一层一层向上寻找,直到找到全局作用域还是没找到,就宣布放弃。这种一层一层的关系,就是作用域链 。

2.5 名字空间

用于解决相同的全局变量、相同名字的函数,造成命名冲突。

var NAME_SPACE = {}
NAME_SPACE.name = ''
NAME_SPACE.sum = function() {}
2.6 常量

let、var声明的是变量,要声明一个常量,使用ES6的const声明,通常用全部大写的变量来表示“这是一个常量,不要修改它的值”,谷歌浏览器下,赋值会报错。

const PI = 3.14
PI = 3 // index.html:53 Uncaught TypeError: Assignment to constant variable.
console.log(PI)
2.7 解构赋值

可以同时对一组变量进行赋值

  • 数组解构(注意嵌套层次和位置要保持一致)
let arr = ['诸葛亮', ['刘备', '关羽'], '张飞'];
let [o, [p,q], r] = arr;
console.log(o,p,q,r) //诸葛亮 刘备 关羽 张飞
  • 对象进行解构赋值
    正常解构
let obj = {name: '张飞',age: 37,country: '蜀国'
}
let {name, age, country} = obj
console.log(name,age,country) //张飞 37 蜀国

嵌套的对象属性进行赋值:
address不是变量,而是为了让country、province、city获得嵌套的address对象的属性

let obj = {name: '张飞',age: 37,address: {country: '蜀国',province: '四川',city: '成都'}
}
let {name, age, address:{country,province,city}} = obj
console.log(name,country,province,city) //张飞 蜀国 四川 成都   
console.log(address) //Uncaught ReferenceError: address is not defined

当解构赋值,对应属性不存在时,会赋值undefined

let obj = {key: '004',name: '张飞',age: 37,address: {country: '蜀国',province: '四川',city: '成都'}
}
// key不是变量,而是为了让变量code获得key属性
let {name,id,key:code} = obj
console.log(name) //张飞
console.log(id) // undefined
console.log(code) // 004

解构赋值还可以使用默认值

let obj = {key: '004',name: '张飞',age: 37,address: {country: '蜀国',province: '四川',city: '成都'}
}
let {name,id='001'} = obj
console.log(name) //张飞
console.log(id) // 001
  • 使用场景
    1、直接获取某对象里面的属性值,不需要通过.来获取和连续声明变量
let {x,y,z} = {}

2、函数接收一个对象作为参数,可以直接用解构把对象属性赋值给变量

sum({x,y,z=0}){return x+y+z
}

3、变量值替换,减少中间变量

let x=1, y=2;
[x,y] = [y,x]
console.log(x,y) //2 1

三、方法

一个对象中绑定函数,这个函数称为这个对象的方法。

let obj = {name: '张飞',birth: 1993,age: function() {let y = new Date().getFullYear()return y - this.birth}
}
console.log(obj.age()) //30
3.1 this指向

this是执行环境上下文对象 ,它指向谁取决于它什么时候被调用、被谁调用。

  • 在方法中,this表示该方法所属的对象
    也就是说,谁执行这个方法,this就指向谁
let person = {name: '张飞',birth: 1993,say: function() {console.log(this)console.log(this.name)}
}
// person对象调用了方法,this指向person
person.say()
let person = {name: '张飞',birth: 1993,say: function() {console.log(this)console.log(this.name)}
}
// 全局对象调用say方法,因此this指向window
let say = person.say
say()
  • 单独使用,this 表示全局对象,浏览器中指向向window
  • 函数中使用this,表示全局对象,浏览器中指向向window
  • 事件中的this,指向了接收事件的 HTML 元素
  • 显示函数绑定
    js中函数也是对象,对象中则有方法,apply 和 call 就是函数对象的方法,他们允许切换函数执行的上下文环境(context),即 this 绑定的对象。
let personBase = {name: '张飞',birth: 1993,say: function() {console.log(this)console.log(this.name)}
}
let person = {name: '刘备',
}
let say = personBase.say
say.call(person) //指向person
say.apply(personBase) //personBase

1.2 调用函数扩展

  • 函数名(实参列表):say(a,b)
  • 函数名.call(执行环境对象,实参列表):say.call(person,a,b,c…)
    call 方法用来改变 this 的指向,第一个参数表示 this 的指向,后面的参数表示传递的实参,可以零个、一个或多个
  • 函数名.apply(执行环境对象,实参列表数组):say.apply(person,[a,b,c])
    apply 方法和 call 方法基本相同,也是用来改变 this 的指向,不同点在于,apply 传递实参时,采用数组的形式。
  • 函数名.bind(执行环境对象)(实参列表):say.bind(person).(a,b,c)
    bind 也是用来改变 this 的指向的,但是 bind(执行环境对象) 返回的是函数,还没有被执行,需要再使用()执行函数。
  • 回调函数
    主函数的事先做完,回头再调用传进来的那个函数

四、立即执行函数

声明函数的同时立即调用这个函数,立即执行函数是一个匿名函数

4.1 作用

1、页面加载完成后只执行一次的设置函数。
2、将设置函数中的变量包裹在局部作用域中,不会泄露成全局变量

4.2 书写方式
// a b 形参
(function(a,b){//函数体内容console.log(a,b)
}(1,2));//形参  立即执行函数结束要加分号(function(a,b){console.log(a,b)
})(3,4)
4.3 用例

由于log调用前,循环执行结束,所以输出5

for(let i=0; i<6; i++) {function log() {console.log(i)}
}
log() //5

使用立即执行函数

for(let i=0; i<6; i++) {(function(j) {console.log(i)  //0,1,2,3,4,5})(i)
}

五、闭包

闭包是指有权访问另一个函数中的变量函数。(定义一个在函数内部的函数,内部函数可以访问外包函数的局部变量)

5.1 闭包形成条件
  • 函数嵌套
  • 内部函数使用到了外部函数内容(变量、函数等)
  • 参数和变量不会被回收
function fun () {var x = 0, y = 1;function sum() {console.log(x + y)return x + y}return sum
}
let f = fun()
f()
5.2 闭包的作用
  • 可以读取函数内部的变量
  • 让这些变量的值始终保持在内存中
function fun () {var n = 0;function sum() {n += 1console.log(n)}return sum
}
var f = fun()
f() //1
f() //2

fun执行两次, n分别输出1 和 2,说明fun中的局部变量n一直存在内存中,没有在fun调用后,自动清除。
未清除的原因:sum函数是fun的子函数,fun执行后,把sum函数赋值给了全局变量f,全局变量f一直存在,所以sum函数一直存在,而sum又依赖于fun函数,所以fun一直存在内存中,未在调用结束后被垃圾回收机制回收。

5.3 闭包的注意事项
  • 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题
  • 闭包会在父函数外部改变父函数内部变量的值。所以,如果你把父函数当作对象使用,把闭包当作它的公用方法,把内部变量当作它的私有属性,这时一定要小心,不要随便改变父函数内部变量的值。多个子函数都是同时指向父级,是完全共享的。因此当父级的变量对象被修改时,所有子函数都受到影响

六、箭头函数

箭头函数相当于匿名函数,简化了函数定义

6.1 定义方式
// 省略简写方式
let fun1 = (x,y)=> x+y;// 多条语句
let fun2 = (x,y)=> {console.log(x)return x+y
}
fun1(1,2)
fun2(2,3)
6.2 this问题

箭头函数内部的this是词法作用域,由上下文确定。
箭头函数的外层如果有普通函数,那么箭头函数的this就是这个外层的普通函数的this,箭头函数的外层如果没有普通函数,那么箭头函数的this就是全局变量。

  • 箭头函数是匿名函数,不能作为构造函数,不可以使用new命令,否则后抛出错误
    箭头函数没有原型对象prototype这个属性
  • 箭头函数不绑定arguments,取而代之用rest参数解决,同时没有super和new.target
  • 箭头函数可以通过拓展运算符获取传入的参数。
let fun2 = (...args)=> {console.log(args)return args[0]+args[1]
}
fun2(2,3)
  • 使用call,apply,bind并不会改变箭头函数中的this指向
    当对箭头函数使用call或apply方法时,只会传入参数并调用函数,并不会改变箭头函数中this的指向。
    当对箭头函数使用bind方法时,只会返回一个预设参数的新函数,并不会改变这个新函数的this指向。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/84434.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何用一行CSS实现10种现代布局

现代 CSS 布局使开发人员只需按几下键就可以编写十分有意义且强大的样式规则。上面的讨论和接下来的帖文研究了 10 种强大的 CSS 布局&#xff0c;它们实现了一些非凡的工作。 超级居中&#xff1a;place-items: center 对于第一个“单行”布局&#xff0c;让我们解决所有 CSS…

缓存读写淘汰算法W-TinyLFU算法

在W-TinyLFU中&#xff0c;每个缓存项都会被赋予一个权重。这个权重可以表示缓存项的大小、使用频率、是否是热数据等因素。每次需要淘汰缓存时&#xff0c;W-TinyLFU会选择小于一定阈值的权重的缓存项进行淘汰&#xff0c;以避免淘汰热数据。 另外&#xff0c;W-TinyLFU也会根…

分析数组,结构体在反汇编中存储

本文会在IDA中分析数组&#xff0c;结构体在内存中的存储 目录 IDA分析数组存储 IDA分析结构体存储 传递参数的方式 IDA分析数组存储 测试代码如下&#xff1a; /************************************************************************/ /*Author : 玄都大…

已解决 Kotlin Error: Null can not be a value of a non-null type String

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页: &#x1f405;&#x1f43e;猫头虎的博客&#x1f390;《面试题大全专栏》 &#x1f995; 文章图文并茂&#x1f996…

Intel汇编在VS下开发的环境配置

1. 创建一个C/C的空项目 2. 创建汇编源码文件, 就是C文件改后缀为asm 3. 在生成依赖项一栏中选择自定义 4. 选择masm 5. 在源文件上右击选择属性 6. 这么设置一下 7. 为了让代码看的更舒服一些, 添加一些高亮插件 8. 安装AsmHighligher和AsmDude插件(非必须), 其中前者主要是高…

signal(SIGPIPE, SIG_IGN)

linux查看signal常见信号。 [rootplatform:]# kill -l1) HUP2) INT3) QUIT4) ILL5) TRAP6) ABRT7) BUS8) FPE9) KILL 10) USR1 11) SEGV 12) USR2 13) PIPE 14) ALRM 15) TERM 16) STKFLT 17) CHLD 18) CONT 19) STOP 20) TSTP 21) TTIN 22) TTOU 23) URG 24) XCPU 25) XFSZ 2…

【动态规划刷题 16】最长等差数列 (有难度) 等差数列划分 II - 子序列

1027. 最长等差数列 https://leetcode.cn/problems/longest-arithmetic-subsequence/ 给你一个整数数组 nums&#xff0c;返回 nums 中最长等差子序列的长度。 回想一下&#xff0c;nums 的子序列是一个列表 nums[i1], nums[i2], …, nums[ik] &#xff0c;且 0 < i1 <…

学Python的漫画漫步进阶 -- 第十一步.常用的内置模块

学Python的漫画漫步进阶 -- 第十一步.常用的内置模块 十一、常用的内置模块11.1 数学计算模块——math11.2 日期时间模块——datetime11.2.1 datetime类11.2.2 date类11.2.3 time类11.2.4 计算时间跨度类——timedelta11.2.5 将日期时间与字符串相互转换 11.3 正则表达式模块—…

音乐随行,公网畅享,群辉Audiostation给你带来听歌新体验!

文章目录 本教程解决的问题是&#xff1a;按照本教程方法操作后&#xff0c;达到的效果是本教程使用环境&#xff1a;1 群晖系统安装audiostation套件2 下载移动端app3 内网穿透&#xff0c;映射至公网 很多老铁想在上班路上听点喜欢的歌或者相声解解闷儿&#xff0c;于是打开手…

代码随想录算法训练营第23期day2 | 977.有序数组的平方 、209.长度最小的子数组、59.螺旋矩阵II

目录 一、&#xff08;leetcode 977&#xff09;有序数组的平方 1.暴力解法 2.双指针法 二、&#xff08;leetcode 209&#xff09;长度最小的子数组 1.暴力解法 ​编辑2.滑动窗口 三、&#xff08;leetcode 59&#xff09;螺旋矩阵II 一、&#xff08;leetcode 977&…

ChatGLM 配置CUDA使用GPU本地训练

Cuda的下载及安装 cuda版本 由于显卡的不同,需要先查看我们显卡及驱动最高支持的cuda。 进入cmd输入nvidia -smi 版本支持向下兼容,为了保证能够和其他开发库版本兼容,这里使用的CUDN版本为11.6. cuda下载 CUDA Toolkit| NVIDIA Developer官网找到对应CUDA版本。(我这里…

【Python基础】S01E02 列表

S01E02列表 列表是什么列表的操作修改、添加和删除元素列表排序列表倒序列表长度遍历整个列表 数值列表创建数值列表数值列表简单统计计算列表推导式 列表切片复制列表 列表是什么 在Python中&#xff0c;用方括号&#xff08;[ ]&#xff09;表示列表&#xff0c;用逗号分隔其…

基于Java的Base64编解码优化探讨

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

eclipse svn插件安装

1.进入eclipse的help->Eclipse Marketplace,如下图所示&#xff1a; 2.输入“svn”,再按回车&#xff0c;如下图&#xff1a; 3.这我选择的是 Subversive,点击后面的“install”按钮&#xff0c;如下图 Eclipse 下连接 SVN 库有两种插件 —— Subclipse 与 Subversive &…

java面向对象(八)

文章目录 一、abstract关键字的使用1.概念2. abstract修饰类:抽象类3.abstract修饰方法&#xff0c;抽象方法4.abstract使用上的注意点&#xff1a;5.抽象类的匿名子类 二、计算一段代码执行所花费的时间三、接口的使用1.接口的使用2.定义接口中的成员3.代码demo4.Java类可以实…

uniapp:APP开发,后台保活

前言&#xff1a; 在ios中&#xff0c;软件切换至后台、手机息屏&#xff0c;过了十来秒软件就会被系统挂起&#xff0c;APP内的任务就不能继续执行&#xff1b;在android中&#xff0c;默认情况下&#xff0c;软件在后台运行的时候&#xff0c;触发某些特定条件的情况下&…

高性能实践

1、认识性能 从用户体验来看&#xff0c;性能就是响应时间短&#xff1b; 从开发角度来看&#xff0c;性能主要是执行效率高。 性能主要表现形式如下&#xff1a; &#xff08;1&#xff09;响应时间&#xff0c;AVG、MAX、MIN、TP95、TP99 &#xff08;2&#xff09;吞吐…

物联网网关:连接设备与云端的桥梁

物联网网关作为连接设备与云端的桥梁&#xff0c;承担着采集数据、设备远程控制、协议转换、数据传输等重要任务。物联网网关是一种网络设备&#xff0c;它可以连接多个物联网设备&#xff0c;实现设备之间的数据传输和通信。物联网网关通常具有较高的网络带宽和处理能力&#…

浙江大学《乡村振兴战略下传统村落文化旅游设计》许少辉八一著作——2023学生开学季辉少许

浙江大学《乡村振兴战略下传统村落文化旅游设计》许少辉八一著作——2023学生开学季辉少许

代码随想录算法训练营第一天(C)| 704. 二分查找 27. 移除元素

文章目录 前言一、704. 二分查找二、27. 移除元素三、34. 在排序数组中查找元素的第一个和最后一个位置总结 前言 这次是C&#xff1b; 代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素_愚者__的博客-CSDN博客 &#xff08;java&#xff09; 一、704. 二分查找 的优…