函数进阶
变量提升和函数提升
变量提升
js中,var变量在声明之前就允许被访问
<script>
// 访问变量 str
console.log(str + 'world!');
// 声明变量 str
var str = 'hello ';
</script>
总结:
- 变量在未声明即被访问时会报语法错误
- 变量在声明之前即被访问,变量的值为
undefined
let
声明的变量不存在变量提升,推荐使用let
- 变量提升出现在相同作用域当中
- 实际开发中推荐先声明再访问变量
注:关于变量提升的原理分析会涉及较为复杂的词法分析等知识,而开发中使用 let
可以轻松规避变量的提升。
函数提升
函数提升与变量提升比较类似,是指函数在声明之前即可被调用。
<script>
// 调用函数
foo()
// 声明函数
function foo() {
console.log('声明之前即被调用...')
}
// 不存在提升现象
bar() // 错误
var bar = function () {
console.log('函数表达式不存在提升现象...')
}
</script>
- 函数提升能够使函数的声明调用更灵活
- 函数表达式不存在提升的现象
- 函数提升出现在相同作用域当中
函数进阶
函数参数
默认值:
<script>
// 设置参数默认值
function sayHi(name="小明", age=18) {
document.write(`<p>大家好,我叫${name},我今年${age}岁了。</p>`);
}
// 调用函数
sayHi();
sayHi('小红');
sayHi('小刚', 21);
</script>
总结:
- 声明函数时为形参赋值即为参数的默认值
- 如果参数未自定义默认值时,参数的默认值为
undefined
- 调用函数时没有传入对应实参时,参数的默认值被当做实参传入
函数的动态参数 传入参数的数量可以不定
动态参数没有形参。 getSum()
arguments
是函数内部内置的伪数组变量,它包含了调用函数时传入的所有实参。
可以传入任意数量参数的求和参数:
function getSum() {
let sum = 0
for (let i = 0; i < arguments.length; i++) {
sum += arguments[i]
}
console.log(sum)
}
getSum(1, 3, 4)
getSum(2, 4, 6, 7, 4, 100)
剩余参数(推荐)
先写一个形参(也可以不写),逗号后面写点点点(…),然后可以紧跟一个形参名作为插入剩余参数的数组名
这个数组是一个真数组(相比于argument等伪数组),可以运用到pop、push等函数
<script>
function config(baseURL, ...other) {
console.log(baseURL) // 得到 'http://baidu.com'
console.log(other) // other 得到 ['get', 'json']
}
// 调用函数
config('http://baidu.com', 'get', 'json');
</script>
...
是语法符号,置于最末函数形参之前,用于获取多余的实参- 借助
...
获取的剩余实参,是个真数组
与剩余函数相似:展开运算符Spread Operator
展开运算符就是三个点:
...
它的作用是:把数组、对象、字符串等“展开”成一个个独立的元素或属性。
数组展开
let arr1 = [1, 2, 3] let arr2 = [...arr1, 4, 5] // 展开arr1的元素 console.log(arr2) // [1, 2, 3, 4, 5]
相当于把
arr1
拆开来塞进arr2
里。
max求最值
Math.max只能传入元素,不能传入数组名。可以用展开符展开。
let arr = [1,2,3,4,5] let max = Matn.max(...arr)
对象展开
let obj1 = { name: "张三", age: 20 } let obj2 = { ...obj1, gender: "男" } console.log(obj2) // { name: "张三", age: 20, gender: "男" }
你可以把一个对象的内容“复制”到另一个对象中,常用于 对象拷贝、合并。
函数传参
function sum(a, b, c) { console.log(a + b + c) } let nums = [1, 2, 3] sum(...nums) // 相当于 sum(1, 2, 3)
克隆数组或对象
let arr = [1, 2, 3] let copy = [...arr] // 克隆一个数组 let obj = { a: 1, b: 2 } let copyObj = { ...obj } // 克隆一个对象
这比传统的
for
或Object.assign
更简洁。
...
展开运算符 = 把“集合”里的东西拆成“一个个的元素”。
箭头函数
箭头函数是一种声明函数的简洁语法,它与普通函数并无本质的区别,差异性更多体现在语法格式上。
引入箭头函数的目的是更简短的函数写法且不绑定this,箭头函数的语法比函数表达式更简洁。
它用于本来需要用在匿名函数的地方。
基本语法:
const fn = function () {
console.log(123)
}
// 1. 箭头函数 基本语法
const fn1 = () => {
console.log(123)
}
fn()
const fn = (x) => {
console.log(x)
}
fn(1)
// 2. 只有一个形参的时候,可以省略小括号
const fn = x => {
console.log(x)
}
fn(1)
// 3. 只有一行代码的时候,我们可以省略大括号
const fn = x => console.log(x)
fn(1)
// 4. 只有一行代码的时候,可以省略return
const fn = x => x + x
console.log(fn(1))
// 5. 箭头函数可以直接返回一个对象
const fn = (uname) => ({ uname: uname })
console.log(fn('刘德华'))
箭头函数的参数
可以传入剩余参数,不能使用动态参数。
const sum = (...arr) =>
<script>
// 以前this的指向: 谁调用的这个函数,this 就指向谁
// console.log(this) // window
// // 普通函数
// function fn() {
// console.log(this) // window
// }
// window.fn()
// // 对象方法里面的this
// const obj = {
// name: 'andy',
// sayHi: function () {
// console.log(this) // obj
// }
// }
// obj.sayHi()
// 2. 箭头函数的this 是上一层作用域的this 指向
// const fn = () => {
// console.log(this) // window
// }
// fn()
// 对象方法箭头函数 this
// const obj = {
// uname: 'pink老师',
// sayHi: () => {
// console.log(this) // this 指向谁? window
// }
// }
// obj.sayHi()
const obj = {
uname: 'pink老师',
sayHi: function () {
console.log(this) // obj
let i = 10
const count = () => {
console.log(this) // obj
}
count()
}
}
obj.sayHi()
</script>
箭头函数的this
箭头函数不会创建自己的this,它只会从自己的作用域链的上一层沿用this。
<script>
// 以前this的指向: 谁调用的这个函数,this 就指向谁
// console.log(this) // window
// // 普通函数
// function fn() {
// console.log(this) // window
// }
// window.fn()
// // 对象方法里面的this
// const obj = {
// name: 'andy',
// sayHi: function () {
// console.log(this) // obj
// }
// }
// obj.sayHi()
// 2. 箭头函数的this 是上一层作用域的this 指向
// const fn = () => {
// console.log(this) // window
// }
// fn()
// 对象方法箭头函数 this
// const obj = {
// uname: 'pink老师',
// sayHi: () => {
// console.log(this) // this 指向谁? window
// }
// }
// obj.sayHi()
const obj = {
uname: 'pink老师',
sayHi: function () {
console.log(this) // obj
let i = 10
const count = () => {
console.log(this) // obj
}
count()
}
}
obj.sayHi()
</script>