一、事件冒泡
1.介绍
事件冒泡值得是,内层元素和外层元素如果都对某个事件进行监听,那么改事件会一直向上抛出。
这样可以简化开发,比如说一个大的div中有好多小div,可以只对大div的事件进行监听。
2.停止事件冒泡
evt.stopPropagation();//firefox
evt.cancelBubble=true;
写法:
var evt =window.event||event;
if(evt.stopPropagation){
evt.stopPropagation();
}else{
evt.cancelBubble=true;
}
二、闭包
1、js函数定义与执行过程
step1:定义函数的时候js会将函数的scope chain设置为a所在的环境
step2:执行function时,函数会进入相应的excution context。
step3:在创建环境的过程中,首先会为a添加一个scope属性,他的值就是第一步中的scope chain
step4:执行环境会创建一个call object,并把活动对象添加到scope chain的顶端,并在call object中添加arguments属性、形参、内嵌函数和局部变量
2.上述理论的引用(如下代码)
首先定义a时a 的scope chain是window。执行时创建excution context,a的scope = scope chain。接着创建call object,并置于scope chain的顶端,在添加arguments 形参、内嵌函数、局部变量(ps:此时b被创建,并且chain scope是a的现在的scope chain)。当执行b的过程不再赘述,最终形成如下图所示的结构
ps:
当在函数b中访问一个变量的时候,搜索顺序
-
先搜索自身的活动对象,如果存在则返回,如果不存在将继续搜索函数a的活动对象,依次查找,直到找到为止。
-
如果函数b存在prototype原型对象,则在查找完自身的活动对象后先查找自身的原型对象,再继续查找。这就是Javascript中的变量查找机制。
-
如果整个作用域链上都无法找到,则返回undefined。
3.闭包的用处
闭包可以保证自己的公共方法的安全。
因为,一个函数会按照scope chain中call object的顺序寻找变量。这样如果将公共的js库定义成闭包,那么无论使用者定义的变量名字是什么都不会影响到公共库的代码,因为公共库的定义的变量所存放的call object对象必然在使用者定义的前面。
三、元素绑定事件
方法1:静态绑定
直接在html标签里写上事件
方法2;动态绑定
首先,获取相应的元素对象。然后,通过元素.事件名=function绑定
方法3:通过元素内置方法绑定
Firefox
addEventListener(“click”,handerfunction,false(常用false,因为事件由内向外传递))
第一个参数是事件,第二个是方法,第三个是事件传递顺序
RemoveEventListner移除事件
addEventListener方法的this指向元素对象
IE
attachEvent(“onclick”,handerfunction);第一个参数是事件名,第二个参数是函数
detachEvent();移除事件
上面两个函数的this指针指向window
四、对象动态添加属性和动态删除属性
1.delete t.go;动态删除属性 t是对象的引用名字,go是属性名字
2、添加直接用对象名.属性名=???就行了
五、js工厂模式
function createObject(){
var obj = new Object();
obj.uname="test";
obj.add=function(a,b){
alert(a+b)
}
return obj;
}
六、匿名自调用函数
(function(){})()表示执行第一个小括号内的匿名函数对象
七、单例模式之饿汉式
var user={publicVar:'我就是单例',
publicMethod:function(){
alert("换个概念你就不知道了!!!");
}
};
方法二:(注意这里还模拟了java的封装)
var obj =(function(){
var privateVar="哈哈,js很有意思!!!";
function showPrivate(){
alert(privateVar)
}
return {
publicVar:"test",
showPrivate:showPrivate
}
})();
上面的代码使用了匿名自调用函数,并且使用闭包模拟了封装
八、单例模式之懒汉式
var lazyobj =(function(){
var privateVar="哈哈,js很有意思!!!";
function showPrivate(){
alert(privateVar)
}
function init(){
return {
publicVar:"test",
showPrivate:showPrivate
}
}
var instance;
// 获取到单例对象公共方法
function getInstance(){
if(!instance){
instance=init()
}
return instance;
}
return {
getInstance:getInstance
}
})();
var obj1 = lazyobj.getInstance() ;
九、使用函数对象模拟继承
function User(uname,age){
this.uname = uname;
this.age =age;
}
function Teacher(id,uname,age){
this.id = id;
this.method123=User;
this.method123(uname,age );//此时,是Teacher持有User方法,因此,user的this是指向teacher对象的
delete this.method;
}
十、函数原型prototype
原理:构造器里面有一个__proto__ 执行函数对象里面的prototype占据的内存
使用原型模拟继承
function User(uname,age){
this.uname = uname;
this.age =age;
}
function Teacher(id){
this.id=id;
}
Teacher.prototype=new User("test",123);
var t1 = new Teacher(123456);