常量:const
作用:防止数据污染,不能被二次赋值
语法:const 名字 = 值
复杂数据:数据本身可以修改
应用场景
1.数据不想被修改
2.服务器拿到的数据:防止修改
形参默认值
作用: 在定义函数的时候:给形参赋值,这个值就叫做默认值
实例
默认打印99乘法表
function chengFa(level = 9) {
let str = ''
for (let i = 1; i <= level; i++) {
for (let j = 1; j <= i; j++) {
str += `${i} * ${j} = ${i * j} `
}
str += '<br>' }
document.body.innerHTML += str
}
传入参数5:打印55乘法表5乘法表
chengFa(5)
没有参数:打印99乘法表
chengFa()
总结:参数一旦有了默认值:调用的时候如果不传,那么默认值生效;如果传了,实参生效,默认值不生效
解构
解构(解除解构:把复杂的东西简单化)
数组解构
数组解构:按顺序获取元素(与变量名字无关)
语法:let [变量1, 变量2...] = 数组
实例:
let arr = ['apple', 'banana', 'pitch', 'orange', 'watermelon', 'lichi']
let [, , , o, w] =
console.log(o, w)
输出结果
orange watermelon
对象解构
对象解构:按属性名获取数据
语法:let { 属性名1, 属性名2...} = 对象
实例:
let obj = { username: 'xiaomage', password: 'admin123', hobby: ['台球', '钓鱼', '打牌', '抽烟'] }
const { hobby, username } = obj
console.log(hobby, username)
输出结果:
['台球', '钓鱼', '打牌', '抽烟'] xiaomage
扩展:
let a = 1
let b = 2;
// 要求:交换两个变量的值,不允许使用第三方变量
[a, b] = [b, a]
console.log(a, b)
结果为
2 1
剩余运算
作用:获取剩余的内容(不确定数量实参的时候)
常用场景:接收多余的实参
实例:
function max(first, ...others) {
// 第一个实参:给first
// 第二个开始:剩下的都给others,others是一个数组
// console.log(first, others)
let m = first || -Infinity
//Infinity 属性用于存放表示正无穷大的数值。
// 其他的数据是否有比first更大的
// console.log(m)
others.forEach(function (item) {
// 比较
m = item > m ? item : m
})
console.log(m)
}
max()
max(1, 2, 3)
输出结果:
-Infinity
3
扩展:解构中可以使用剩余运算(拆分对象:使用很少)
let obj = { username: 'xiaomage', password: 'admin123', hobby: ['台球', '钓鱼', '打牌', '抽烟'] }
const { hobby, ...others } = obj
console.log(hobby, others)
// 放到对象中使用剩余运算:得到的结果是对象
输出结果:
['台球', '钓鱼', '打牌', '抽烟'] password: "admin123"username: "xiaomage"
剩余运算又叫做拓展运算:可以打散数据,将复杂的数据变得简单
let arr = [1, 3, 2, 9, 5, 4, 8, 6, 7]
求数组中最大值
max(arr) // 输出[1, 3, 2, 9, 5, 4, 8, 6, 7]
// 打散数组,变成单个的参数
max(...arr) // === max(1, 3, 2, 9, 5, 4, 8, 6, 7) 输出
总结
1.剩余:接收多个数据,一般用于形参:...形参变量
2.拓展:展开一个数据变成多个,一般用于实参(数组):...数组实参
3.局限一点: ...无外乎做两件事件:将多个数据变成数组,要么将数组变成多个数据
箭头函数
作用:简化函数的书写
语法:() => {}
-
参数只有1个:省略()
-
代码只有1行:省略{}
自带return
如果有return:一定有{}
this与函数的调用关系
this与函数调用关系:谁调用,this指向谁
-
函数调用模式:所有的函数调用,如果前面没有对象:此时都是window在调用:this一定指向window对象
function fn1() { // window.fn1 = function(){} console.log(this) } fn1() // 本质:window.fn1() -
方法调用模式:函数放到对象内部,是属性值
const obj = { say: function () { console.log(this, this === obj) // 对象内部的this一般都指向对象自己 } } obj.say() -
构造函数模式:new 构造函数()产生孩子对象(暂时不做要求)
function Student() { // 妈妈的肚子 console.log(this) } // Student() // this指向window(当普通函数使用的) const s = new Student() // 出生一个孩子 console.log(s) -
事件函数
<script> let box = document.querySelector('.box') // 事件回调函数的内部的this:指向事件源 box.addEventListener('click', function () { console.log(this) // this指向box元素 // 不管是DOM0(on事件)还是DOM2(add事件),事件回调函数的内部的this都是指向事件源 }) box.addEventListener('click', () => { console.log(this) // 箭头函数:不产生this(找到外面:window对象) // 想要有this必须有function关键字 }) </script> -
借调模式
借调模式:别人有的东西,借过来用:借调的主体就是使用的上下文环境
上下文:代码所处的环境
借调1:被借调函数的主体发生了改变(调用者发生改变)
借调2:条件,为什么要借调? 别人的函数已经做好了某个功能,我当前需要用到那个功能,但是我又不想再写代码:可以借用
// 借腹生子
const richWoman = {
name: '富婆',
makeChild: function () {
// this代表richWoman
console.log(this.name + '重金求子')
}
}
richWoman.makeChild()
// 没钱:想生孩子,
const ds = {
name: '屌丝'
}
// 想借用richWoman.makeChild功能:借用要改变主体
// 1. call借调:目标函数.call(新对象),借一次
// 新对象:修改目标函数里面的this,修改函数的归属权
richWoman.makeChild.call(ds)
// 借调的目的:节省代码,提升开发效率
// 目的很明确:但是现实很骨感:想要使用借调开发,前提是对别人的函数内部的代码要了如指掌
其他方式:
// 定义一个函数实现求和功能
let obj = {
add: function (a, b) {
console.log(this, a + b)
}
}
假设这个功能很复杂,别的地方要使用需要借调
借调有三种方式
-
call:一次性借调,借调后立即执行,目标函数.call(对象,对函数的传参,按顺序
obj.add.call(null, 1, 2) // null是不会修改this的,this指向window对象 -
apply:一次性借调,跟call一样:传参的方式,必须传入数组(方便调用者选择)
obj.add.apply({}, [1, 2])// 为什么要设计两个?方便调用者 let a = 1 let b = 2 obj.add.call({}, a, b) let c = [1, 2] // call使用 obj.add.call({}, c[0], c[1]) // 麻烦 obj.add.apply({}, c) // 其实:记住一个就可以,call obj.add.call({}, ...c) // call和apply只有传参的区别:其他一模一样 -
bind:永久性借调,借过来之后,可以重复用
目标函数.bind(对象,顺序传参)
bind返回一个结果:被借调后(修改了this之后)的函数副本
let res = obj.add.bind({}, 3, 4)
console.log(res)
res()
res()
// bind一次性调用
obj.add.bind({}, 10, 20)()
// bind大家会见到:用来改名(Vue会用到)
let f = obj.add.bind({})
console.log(f)
f(1, 2)
f(2, 3)
总结
-
借调是好东西,但是不会没有关系(不影响开发 ,影响效率)
-
长期学习的过程:需要掌握系统的API的源代码(自己也能定义函数实现)
-
借调有三种方式:call \ apply \ bind
call和apply是一样的:一次性借调,传参有点区别
bind:永久性借调,传参与call一样