JS4
一、事件冒泡
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);