作用域:
1、全局作用域之外,每个函数都会创建自己的作用域,作用域在函数定义时就已经确定了。而不是在函数执行时
2、函数的作用域时静态的,只要函数定义好就一直存在,且不会发生改变
复制代码
面试题:
var x= 10
function fn(){
console.log(x)
}
function show(fn){
var x = 20
fn()
}
show(fn) //20
复制代码
var fn = function(){
console.log(fn)
}
fn()
var obj = {
fn2: function(){
console.log(fn2)//报错,es6才存在块级作用域,所以沿着作用域就找到了window所以报错
console.log(this.fn2)// this就是谁调用了这个函数,this=>obj(duithis的理解比较差)
}
}
复制代码
闭包
看一段代码:
html代码
<button>测试1<button>
<button>测试1<button>
<button>测试1<button>
js代码
document.getElementsByTagName('button')
for(var i = 0,length = btns.length;i<length;i++){
var btn = btns[i]
btn.onclick = function(){ //注册事件 dom(对应下标)元素事件添加 onclick
console.log(`这时第${i+1}个 i`)
}
}
复制代码
进化版
for(var i = 0,length = btns.length;i<length;i++){
;(function(i){
var btn = btns[i]
btn.onclick = function(){ //注册事件 dom(对应下标)元素事件添加 onclick
console.log(`这时第${i+1}个 i`)
})(i) //i 读取的是 for循环的 i
}
复制代码
1、如何产生闭包
当一个嵌套的内部(子)函数引用了嵌套的外部(父亲)的变量时就产生了闭包。(这是内部函数已经加载)
2、产生闭包的条件
函数嵌套
内部函数引用了外部函数的数据(变量/函数)
复制代码
常见的闭包
function fn1(){
var a = 2
function fun2(){ //函数定义已经被提什么了(函数定义已经被执行)
a++
console.log(a)
}
return fun2
}
var fun3 = fun1() // fun3指向 fun2 所以 fun2没有成为回收对象
fun3() //3
fun3() //4
fun3 = null //闭包死亡 (包含闭包的的函数对象成为垃圾对象) fun3指向的就是 fun2(?????)
复制代码
闭包的作用
1、使用函数内部的变量在函数执行完后,任然存活在内存中(延长局部变量的生命周期)
2、让函数外部可以操作(读写)到函数内部的数据(函数/变量)
函数执行完毕之后,函数内部声明的局部变量(一般不存在)如果产生闭包,外部依然有变量指向这个函数。
函数外部不能直接访问函数内部的局部变量,通过闭包让外部的得到返回函数,
并给予变量指向(var fun3 = fun1()),没有这个指向fun2()完成执行没有执行就会成为回收对象,
复制代码
闭包的生命周期
1、产生:在嵌套内部函数定义执行完成时就产生了(是不在调用) 变量声明式恰恰是
2、死亡:在嵌套的内部函数成为垃圾对象时
3、 fun3 = null
复制代码
自定义JS模块
1、具有特点功能的js文件
2、将所有的数据和功能封装在一个函数内部(私有的)对象可以直接访问到属性,所以需要一个函数
3、只向外暴露一个或n个方法的方法或属性
4、
复制代码
function myModule(){
var mes = 'tianze'
function doSomething(){
console.log(`doSomething${mes.toUpperCase}`)
}
function doOtherthing(){
console.log(`doSomething${mes.toLowerCase}`)
}
return {
doSomething :doSomething, //返回一个对象 对象的俩个属性保存的是俩个方法,通过访问属性去执行方法
doOtherthing : doOtherthing,
}
}
复制代码
引用使用
myModule().doSomething() //执行函数后才能得到这个对象
myModule().doOtherthing()
复制代码
第二种方式:
;(function(){
var mes = 'tianze'
function doSomething(){
console.log(`doSomething${mes.toUpperCase}`)
}
function doOtherthing(){
console.log(`doSomething${mes.toLowerCase}`)
}
window.moudle= {
//给window添加属性moudle 是一个对象{ 对象俩个属性 指向的俩个 =>function(可以这么理??)}
//代码压缩
doSomething :doSomething,
doOtherthing : doOtherthing,
}
})()
复制代码
引用使用
moudle.doSomething()
moudle.doOtherthing()
复制代码
内存溢出
闭包缺点:函数执行后,函数的局部变量没有释放,占用内存时间过长,容易造成内存泄露。
解决办法:能不用的情况下尽量不用。
复制代码
内存泄漏
占用的内存没有及时释放,
内存泄露积累多了就容易导致内存溢出
常见的内存泄漏:
(1)意外的全局变量 //=>没有使用 var /let 声明变量
(2)没有即使的清理定时器和回调函数
复制代码
问题:
var name = 'The Window'
var object = {
name : 'My Object'
getNameFunc : function(){
return : function(){
return: this.name;
}
}
}
console.log(object.getNameFunc()())
//这个object.getNameFunc() 执行返回的是一个函数,在全局执行函数 this指向window
复制代码
var name2 = 'the Window'
var object2 = {
name2 : 'My Object'
getNameFunc : function(){
var that = this //使用that 保存 this =>就是 object2
return function(){
return that.name
}
}
}
console.log(object2.getNameFunc()())
//My Object object2.getNameFunc()()执行返回的就是 =>return object2.name
复制代码
这个题目(待解析)
function fun(n,o){
console.log(o)
return {
fun:function(m){
return fun(m,n)
}
}
}
var a = fun(0) //a.fun(1) ;a.fun(2); a.fun(3) //输出结果
var b = fun(0).fun(1).fun(2).fun(3); //输出结果
var c = fun(0).fun(1); c.fun(2); c.fun(3); 输出结果
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END