阻止事件冒泡
方法一:
- 事件对象中的stopPropagation()函数可以阻止事件冒泡
- 阻止事件冒泡方法,在阻止对象的前一级阻止
<div><span>选择班级</span>
<ul>
<li>一班</li>
<li>二班</li>
<li>一班</li>
<li>二班</li>
<li>一班</li>
<li>二班</li>
<li>一班</li>
<li>二班</li>
</ul>
</div>
document.getElementsByTagName("div")[0].onclick=function(){
document.getElementsByTagName("ul")[0].style.display="block";
}
//绑定班级选择事件
document.getElementsByTagName("ul")[0].onclick=function(e){
e =e||window.event;
var target=e.target;
document.getElementsByTagName("span")[0].innerText =target.innerText;
//隐藏班级列表
document.getElementsByTagName("ul")[0].style.display="none";
e.stopPropagation();
};
方法二:使用将cancelBubble属性设置为true阻止冒泡,默认值是false,表示允许冒泡
- 在早期ie版本中并不支持stopPropagation,而是使用将cancelkBubble属性设置为true阻止冒泡
document.getElementsByTagName("ul")[0].style.display="none";
// e.stopPropagation();
e.cancelBubble = true;
};
取消事件默认行为
- 有些时候页面元素的默认行为需要阻止
- 事件对象的preventDefault函数阻止默认行为
- 使用return false
//为回到顶部绑定js事件
document.getElementsByTagName("a")[0].onclick=function(e){ //事件的响应比默认行为块,才能在事件中阻止默认行为,形参相当于局部变量,不需要声明
e = e||window.event;
// console.log(document.body.scrollTop);
// e.preventDefault();
return false;
};
匿名自执行函数
创建匿名函数后,该函数立即执行。
- 用括号括起来,告诉函数这是一个整体
(function(str){
console.log(str); //用括号括起来,告诉函数这是一个整体
})("我没有名字");
- 加括号,让解释器把这个当成独立的整体
(function (str){
console.log(str);
}("我是雷锋")); //加括号,让解释器把这个当成独立的整体
- 借用逻辑运算符+-!~
!function(str){ //比较常用!
console.log(str);
}("你是谁")
~function(str){
console.log(str);
}("你是谁4")
+function(str){
console.log(str);
}("你是谁+")
-function(str){
console.log(str);
}("你是谁-")
其他让匿名函数执行的方式
var fn = function(str){ //左侧是变量,右侧匿名函数,两个创建,靠变量执行,依赖了变量
return str;
}("变量");
console.log(fn);
console.log(typeof [function(str){ console.log(str);}("我是大商股份?")]);//我是大商股份?
//匿名函数借用数组,函数返回值赋值给数组下标为0 的值
[][0]=function(str){ console.log(str);}("我是大商股份?"); //我是大商股份?
函数高级应用场景
- 函数在js中被称作一等公民
- 函数作为参数
var interval = setInterval(function(){
console.log(1111);
clearInterval(interval);
},1000);
- 函数内部嵌套函数
function outer(){; //作用域链,右下到上
var a =100,b = 200;
function inner(){
return a+b;
}
var c =inner();
return c;
}
var d = outer();
console.log(d);
- 函数作为另一个函数的返回值
function fn(){
return function(){
console.log("我是被返回的函数!")
};
}
fn();
var f1 =fn(); //返回的是函数
f1();//在调用函数
闭包
- 闭包:是被外层函数返回的,使用外层函数变量的一个内部函数。
- 闭包功能:通过外层函数开创独立的命名空间,内部代码不会污染外部空间(不会干扰外部),而外部代码也不能破坏内部作用域中的变量和数据
- 闭包滥用带来的问题:由于闭包持有的上层作用域在闭包有效的状态下,也必须一直有效,所有滥用闭包会导致大量内存空间被长期占用而不被释放,可能导致性能缓慢,甚至内存泄漏(内存中空间持续占用,不被释放,为内存泄漏。
- 正常情况下,局部变量会被销毁,在这里num会随着函数执行会被增加,闭包就是提供了为全局使用内部作用域中内容的途径。封闭空间中提供了一个访问的通道
- 当闭包不需要再使用时,可以释放闭包
- bib=null;
var num=200;
return function(){
num+=50;
console.log(num);
};
}
var bib = outer(); //返回一个函数,有一个全局变量作用函数,里面的返回函数不能被销毁,这个函数用的变量也会保持长期有效
bib();
//如果不用讲全局变量设置的值为bib=null;
console.log(num);
//当闭包不需要再使用时,可以释放闭包
// bib=null;
// var num=300;
function outer(){
var num = 200;
return function(){
num+=50;
console.log(num); //250
};
}
var bib = outer();
bib();//250
bib(); //300
21点游戏案例
//创建一个21点游戏函数
var counter = (function (){
var total =0;
return function(num){
total+=num;
if(total>21){
total=0;
console.log("loser,回家去!");
}else if(total==21){
total=0;
console.log("算你运气好!");
}else{
console.log("加油!!");
}
};
})();
// var counter = count21();
counter(18); //加油
counter(3);//算你运气好
- 主意:在函数内部用var声明是局部变量,如果没写var,表示全局变量,不建议使用,不规范
- 将内层函数提供给全局作用域的方式,并不只局限于return
- 方法一:使用闭包模拟一个常量,全大写的只有缩写(HTML,JSON)或者变量不允许修改,可以使用,叫做常量
- 变量声明时如果不使用 var 关键字,那么它就是一个全局变量,即便它在函数内定义
变量生命周期
- 全局变量的作用域是全局性的,即在整个JavaScript程序中,全局变量处处都在。
- 而在函数内部声明的变量,只在函数内部起作用。这些变量是局部变量,作用域是局部性的;函数的参数也是局部性的,只在函数内部起作用。
JavaScript 内嵌函数
- 所有函数都能访问全局变量。
- 实际上,在 JavaScript 中,所有函数都能访问它们上一层的作用域。
- JavaScript 支持嵌套函数。嵌套函数可以访问上一层的函数变量。
- 该实例中,内嵌函数 plus() 可以访问父函数的 counter 变量
var getVersion =(function(){
var version = "10086";
return function(newVersion){
return version = newVersion; //一次返回多个参数,需要一个容器,用对象装
};
})();
console.log(typeof getVersion); //function
console.log(getVersion()); //10086
//为version提供修改功能
//数据封装,封装参数
var confUtil=(function(){
var conf ={
version:10086,
size:"xxl",
date:"2017809"
};
return {
getPro:function(proName){ //获取名字
return conf[proName]; //返回拿到的对象
},
setPro:function(proName,proValue){
conf[proName]=proValue;
},
delPro:function(proName){
delete conf[proName];
}
}; //返回装着很多函数的对象
})();
console.log(confUtil); //包含三个函数的对象
console.log(confUtil.getPro("size"));//xxl
console.log(confUtil["getPro"]("size")); //xxl
console.log(confUtil.setPro("size","xxxxl"));//修改size里面的值xxxxl
console.log(confUtil["setPro"]("size","xxxxl"));
console.log(confUtil.delPro("data")); //undefined
console.log(confUtil.view()); //Object {version: 10086, size: "xxxxl"}
js为什么要传window?
- 引用数据类型传的是地址,将window传入,它自身有window并且地址直接指向全局中的window,不需要通过找到外层函数,再去找window那么函数会直接找到window,可以优化代码
(function(w){
var version = "10086";
w.getVersion=function(){
return version ;
};
})(window);
for典型案例
绑定事件(3个按钮点击事件)
var btns = document.getElementsByTagName("input");
for(var n = 0;n<btns.length;n++){
btns[n].onclick =function(){
console.log(n+1); //4,4,4
}
}
- 案例解析:全部变成4,函数内部的代码是consoel.log,函数内部没有变量n,for里面有一个变量n,且n的3时,for循坏是3时结束了。绑定完事件,当n变成3,才触发事件,此时n就是3
- 需要的是绑定事件的那一刻的n
- 方法一:
for(var n = 0;n<btns.length;n++){
btns[n].index=n+1;//将123放在三个函数里面
btns[n].onclick =function(){
console.log(this.index); //将值放在事件的属性上
};
}
方法二:
for(var n = 0;n<btns.length;n++){ //匿名自执行函数
(function (a){
btns[a].onclick =function(){
console.log(a+1); //btns事件函数就是闭包,因为btns是全局的按钮
}
})(n);
}
- console.log(n); //for循坏里面的n,也是全局变量
- for里面有3个函数,有3个独立的模块
- 自动触发
for(var n = 0;n<3;n++){ //setTimeout,独立的,for执行结束此时n为3,
(function(n){
setTimeout(function(){ //等了就变成最后的值
console.log(n);
},1000);
})(n);
// setTimeout(function(n){ //等了就变成最后的值
// console.log(n);
// },1000); //输出3个值,都是3 ,解决方案,外层套一个匿名自执行函数
// console.log(n); //0,1,2
}
匿名自执行函数的方式有3种
- 匿名自执行函数,创建匿名函数后,该函数立即执行。
- 用括号括起来,告诉函数这是一个整体
;(function(str){
console.log(str); //用括号括起来,告诉函数这是一个整体
})("我没有名字");
- 加括号,让解释器把这个当成独立的整体
(function (str){
console.log(str);
}("我是雷锋"));
- 借用逻辑运算符+-!~
!function(str){ //比较常用!
console.log(str);
}("你是谁")
~function(str){
console.log(str);
}("你是谁4")
+function(str){
console.log(str);
}("你是谁+")
-function(str){
console.log(str);
}("你是谁-")
匿名函数的功能
- 匿名自执行函数最突出的功能,开辟类似块级作用域的独立命名空间。内部变量不会对外部产生污染,将各个非全局功能模块封装在独立命名中,可以有效的避免相互干扰。
其他让匿名函数执行的方式
var fn = function(str){ //左侧是变量,右侧匿名函数,两个创建,靠变量执行,依赖了变量
return str;
}("变量");
console.log(fn);
console.log(typeof [function(str){ console.log(str);}("我是大商股份?")]);//我是大商股份?
//匿名函数借用数组,函数返回值赋值给数组下标为0 的值
[][0]=function(str){ console.log(str);}("我是大商股份?"); //我是大商股份?