一、函数的定义方式
1、函数声明
function demo1() {var num = 12var result = Math.pow(num,2)//指数函数return result
}
2、函数表达式
var demo2 = function (x,y) {
//内置对象arguments前面的两个参数 是 x,yvar sum = arguments[0] + arguments[1]console.log(sum)
}
3、构造函数
var demo3 = new Function("x","y","return x+y")
二、函数的调用方式
1、函数名()
console.log(demo1())//144
demo(10,20)//30
var re = demo3(1.2,1.3)
console.log(re)//2.5
2、call() / apply()
console.log(demo1.call())//144
console.log(demo1.apply())//144
demo2.call(window, 1, 2)//3
demo2.apply(null, [4, 5])//9
3、自调用
函数表达式自调用
var fn1 = (function () {console.log('this is function')//this is function
})()
匿名函数
(function () {console.log('我是匿名函数')//我是匿名函数
})()
4、对象中的函数调用
var obj = {school: '学校',study: function () {console.log('我是对象的函数')//我是对象的函数},
}
//要用obj去调用 因为所属对象是objobj.study()
5、数组中函数的调用
var arr = [10,'0',undefined,null,false,[2, 3],function () {console.log('我是函数也是数组的元素')//我是函数也是数组的元素console.log(this)//[10, '0', undefined, null, false, Array(2), ƒ, {…}]},{},]arr[6]()
6、函数当做参数调用
function demo4(x) {x()
}
demo4(function () {alert('我是函数也是demo4的参数')//弹窗 我是函数也是demo4的参数
})
7、函数当做返回值的调用
function demo5() {return function () {console.log('我是函数也是demo5的返回值')}
}
demo5()()
如果函数A的返回值是匿名函数B,想要调用匿名函数B 直接再函数A 后面加两个小括号
三、函数中this指向问题(总结)
- 1、在普通函数中this指向window
function fn1() {console.log(this)}
fn1()//window
- 2、在定时器函数中this指向window
var timer = setInterval(function(){console.log(this);//window
},2000)
- 3、在事件函数中this指向事件源
var btn = document.getElementById("btn")
btn.onclick = function() {console.log(this)//btn
}
- 4、在对象函数中this指向当前对象
var name = "this window"
var object = {name: 'this object',getName: function () {//this object在对象函数中this指向当前对象(this指向)console.log(this.name);console.log(name);//this window 当前没有 往上查找(作用域链查找)}
}
object.getName()
- 5、在构造函数中this指向实例化对象
function Person(age,name) {this.age = agethis.name = nameconsoel.log(this)//this指向Person的实例对象p1
}
var p1 = new Person(18,;'张哈哈')
- 6、在原型函数中
- 如果原型调用,this指向原型
- 如果实例化对象调用,this指向实例化对象
- 7、在数组函数中this指向当前数组
四、闭包
1、作用域
有且只有函数 才可以产生作用域
全局作用域(永恒作用域)
- 全局变量
- 在任何作用域内都有效
- 生命周期:浏览器打开时创建,关闭时销毁
局部作用域
- 局部变量
- 只在当前作用域内有效
- 生命周期:函数调用时创建,调用完成后销毁
2、闭包的定义?
- 定义在函数内部的函数
3、闭包的作用?
获取父函数内部的变量
console.log(count)//获取不到 因为count是局部的
var num = 15
function parent() {console.log(num)//15 num是全局的var count = 12.4// 闭包函数的本质// 局部作用域--parent,相对于child作用域是永恒的,本身是作用域是短暂的 function child() {// 局部作用域--childconsole.log(count)}child()
}
parent()
锁住父函数内部的变量
// 随机数案例
var getRandom = function (min, max) {var num = Math.floor(Math.random() * (max - min) + min)return function(){console.log(num);}
}
var result = getRandom(10, 20)
// 两次结果一样 因为父元素执行一次
result()
result()
var btn = document.getElementById("btn")
btn.onclick = (function () {var count = 0return function () {count++console.log(this)//由于事件是异步的,所以自调用的是父函数,此时父函数是匿名函数,所以单击事件调用闭包函数this.innerText = "点赞(" + count + ")"}
})()
4、闭包函数的本质?
- 让父函数相对于闭包函数是永恒作用域
5、闭包作用域之获取复函数内部变量
- this 指向 作用域链的查找规则 预解析 闭包
var name = "this window"
var object = {//不会产生作用域name: 'this object',getName: function () {//局部作用域console.log(this.name);//在对象函数中this指向当前对象console.log(name);//在当前作用域查找 undefinedvar name = "this getName"//var name提升return function () {console.log(this.name);//普通函数 this指向windowconsole.log(name);//this getName 当前作用域没有 往上一级查找}}
}
object.getName()()
var name = "this window"
var object = {//不会产生作用域name: 'this object',getName: function () {//局部作用域console.log(this.name);//this object 在对象函数中this指向当前对象console.log(name);//在当前作用域查找 undefinedvar name = "this getName"//var name提升return function () {function name(){console.log('我是函数声明');}var name = function () {console.log(this.name);//普通函数指向window}//this object 因为this 指向bind(this)中的this bind的指向objectconsole.log(this.name);console.log(name);//this getName函数 当前作用域有name 函数表达式覆盖函数声明name()}.bind(this)return name}
}
object.getName()()