bined(),call(),apply()
参数1表示指定函数里面的this指向那个对象
参数2表示传递参数
bind()方法:修改函数或方法中的this为指定的对象,并且会返回一个修改后的之后的新的函数给我们。- 注意点:
bind()方法除了修改this以外,还可以传递参数,只不过参数必须写在this对象的后面
- 注意点:
call()方法: 修改函数或方法中的this为指定的对象,并且会立即调用修改之后的函数。apply()方法: 修改函数或方法中的this为指定的对象,并且会立即调用修改之后的函数。- 注意点:
apply()方法除了可以修改this以外,还可以传递参数,只不过参数必须通过数组的方式传递
- 注意点:
闭包
概念:闭包就是能够读取其他函数内部变量的函数
闭包的作用:就是可以让你在外界读取函数内部的数据,闭包的原理是利用了函数不销毁的执行空间
注意点:由于函数执行空间,当函数调用完毕后直接销毁,因此外界是无法访问函数内部的变量(作用域 --- 局部作用域)
function closureFn(){
// 私有变量
const a = 66
return function(){
// 返回给外界的函数使用了内部函数的私有变量
console.log(a)
}
}
// 外界有一个变量接收返回的函数
let res = closureFn()
res()
闭包实例
计数器:
<body>
<button>0</button>
<button>0</button>
<script>
// 计数器:一个按钮,当你点击它的时候,让它里面的数值自增
const btn = document.querySelectorAll('button')
// 才有闭包的形式
function counterFn(){
// 私有变量
let counter = 0
// 返回给外界一个函数
return function(){
counter++
return counter
}
}
const fn1 = counterFn()
const fn2 = counterFn()
btn[0].onclick = function(){
this.innerHTML = fn1()
}
btn[1].onclick = function(){
this.innerHTML = fn2()
}
</script>
</body>
封装方法
// 封装方法,可以封装一个加法和减法还有一个计算结果的方
function baseFn(){
// 私有变量
let result = 0
// 设置一个添加的方法
function add(num){
result += num
}
// 设置一个减的方法
function sub(num){
result -= num
}
// 计算的方法
function calc(){
return result
}
// 最终可以把这些方法返回给外界
return {
add,
sub,
calc
}
}
let obj = baseFn()
obj.add(10)
obj.sub(2)
console.log(obj.calc())
缓存数据
缓存数据:如果这个数据是已经存在的,那么就直接从缓存里面获取。如果没有这个数据,那么就添加这个数据
function cacheFn(){
// 声明一个对象来存储缓存数据
const cache = {}
// 返回给外界
// 对象里面存储数据是怎么存储的呢?key=value 形式 || key:value 形式
return function(key, value){
// 判断下有没有设置value值,如果没有设置那么表示的就是获取数据。如果有value值,说明就是设置数据
if(value != undefined){
cache[key] = value
}
return cache[key]
}
}
const result = cacheFn()
console.log(result('username'))
result('username', '张三')
console.log(result('username'))
时间循环
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
const aBtn = document.querySelectorAll('button')
for(var i=0; i<aBtn.length; i++){
// 第二步:由于fn函数已经被调用了,所以进行形参赋值i=0,进入fn函数体里面
function fn(i){
// 第三步:把函数返回给外界,这个返回的函数内部使用了i变量,i变量属于fn函数的私有变量
return function(){
console.log(i)
}
}
// 第一步:把fn(i)赋值给事件了,fn()第一层含义表示函数的调用,直接调用了,并把i=0的这个参数传递给了fn函数本身
// 第四步:aBtn[i].onclick进行赋值,接收到就是function(){console.log(i)}
/*
第五步:当你点击按钮调用这个函数的时候,其实语法变成了以下的形式
aBtn[i].onclick = function(){
console.log(i) // 0
}
*/
aBtn[i].onclick = fn(i)
}
</script>
</body>
立即执行函数(IIFE)
函数不需要其他的方式调用,会直接自己调用
- 语法
(function(){})()(function(){}())!function(){}()~function(){}()
- 特点
- 自己调用自己
- 当函数调用完毕后,存储空间会被销毁
- 作用
- 适合做一些页面初始化的东西
- 和闭包可以一起使用
- 做模块化(伪)
注意点:js里面不能在下一个语句的前面使用()和[]
立即执行函数前最好加分号;
立即执行函数和闭包
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
const aBtn = document.querySelectorAll('button')
for(var i=0; i<aBtn.length; i++){
/*
自执行函数和闭包的结合执行步骤:
+ 第一步:自执行(立即执行)函数会先自调用,自调用的时候把i变量作为实参进行传递
+ 第二步:函数进行形参赋值i=0, 再进入自执行函数体内
+ 第三步:把函数返回给外界,在返回给外界的函数里面使用了私有变量
+ 第四步:外界接收到的就是function(){console.log(i)}
+ 第五步:当你点击按钮执行的时候,实际上是以下形式代码在执行
aBtn[i].onclick = function(){
console.log(i)
}
*/
aBtn[i].onclick = (function(i){
return function(){
console.log(i)
}
})(i)
}
</script>
</body>
立即执行函数模块化
- module
- 把一个功能当成一个模块来使用
- tab选项卡
- 轮播图
- 数据渲染
- 购物车
- 登录验证
- ...
- 一个功能其实就是一个js文件
- 优势
- 方便代码维护
- 优化性能
- 减少变量命名冲突
- 注意点
- 使用自执行函数做的模块化,不是真正的模块化,是一种伪模块化
<script src='cart.js'></script>
<script src='list.js'></script>
<script>
console.log(modCart.index)
console.log(modList.index)
console.log('--------')
modCart.render()
modList.render()
</script>
cart.js
;(function(){
// 私有变量
let index = 0
function render(){
console.log('我是购物车功能!')
}
// 可以把需要在外界使用的数据挂载到window对象上面
window.modCart = {
index,
render
}
})()
list.js
;(function(){
let index = 1
function render(){
console.log('我是列表功能')
}
window.modList = {
index,
render
}
})()