JS---高级进阶

变量对象(Variable Object)

是与执行上下文有关的数据作用域。它是与上下文相关联的特殊对象,用于存储定义在上下文中的变量(Variables)和函数声明(function declarations)。

var x=30;
function bar(){}
(function baz(){});

//全局上下文中的变量对象包含:
x //30
bar //<funciton>

 

活动对象(Activation Object)

当函数被调用者激活时,这个特殊的活动对象就被创建了,活动对象在函数上下文中被作为变量对象(vo)中使用。

function add(x,y){
  var z=x+y;
  function bar(){};
  (function baz(){});
  return z;
}
add(10,20);

"add"函数上下文中的一个活动对象(AO)包括:

形参:x,y  //10,20
实参:参数对象:arguments {0:10,1:20}
局部变量:z //30
内部函数:bar
//函数表达式也不在AO之列

 

作用域链(Scope Chain)

作用域链和原型链很相似,如果在自己的作用域没有,那么它会寻找父级的,直到顶层。

var x=10;

(function foo(){
  var y=20;
  (function bar(){
    var z=30;
    console.log(x+y+z);
  }();
})();

 

 

闭包(Closures)

function foo(){
  var x=10;
  return function bar(){
   console.log(x);
 };
}

//foo返回的也是一个funciton
//并且这个返回的函数可以任意地调用内部变量x

var ret=foo();

var x=20;

ret();//是10而不是20

闭包(因为闭包就是一个函数,而函数是有作用域的)可以有效地将变量隔离,防止出现变量同名的问题(因为一个项目可能有多个人来写)如上例中的外部的x的值不会影响闭包内的x

 

//方法1
function a() {
        var i=0;
        function b() {
            alert(++i);
        }
        return b;
    }
    var c=a();
    c();//1
    c();//2

// 方法2--立即执行函数
    var c=(function() {
        var i=0;
        function b() {
            alert(++i);
        }
        return b;
    })();
    c();//1
    c();//2

1、闭包就是能够读取其它函数内部变量的函数


2、让这些变量的值始终保持在内存中


3、闭包可以保证函数内变量的安全  

 

 

NaN

//NaN表示非数字的意思
typeof NaN //'number'
'a1'==NaN  //false 任何数据和NaN做==比较,结果都是false,包括和自己
NaN==NaN //false

//判断一个数据是不是数字要用isNaN
isNaN('12') //false 函数参数一般为number或string
isNaN('a1') //true

 

if条件是否为真的简写

//条件假
    //number中的0
    //string中的''注意是空字符串,而不是空格串
    //boolean中的false
    //null

if(!x) console.log('条件成立') //当x取值为上述列出的值时,条件成立,反之,不成立

  if(typeof(x)!='undefined' && x)//表示x已定义且不为空

 

JS的继承

//父类
function Person(name,age){
this.name=name;
this.age=age; 
}
//父类方法
Person.prototype.show=function(){
  console.log('my name is '+this.name+','+this.age+' years old.');
}
Person.prototype.hello=function(){
  console.log(this.name+' is saying hello!');
}
//子类
function
Player(name,age,type){
  
Person.call(this,name,age);//或Person.apply(this,[name,age]);
  
this.type=type; }
//子类方法
Player.prototype.show=function(){//子类的同名方法show,因为有了空对象作为桥梁,所以不会覆盖父类方法
  Person.prototype.show.call(this);//子类的去调用父类的同名方法
  
console.log('I am a '+this.type+' player.');
}
Player.prototype.play=function(){
  console.log(this.name+' is playing '+this.type+'.');
}

//子类通过原型链和父类建立关系
function F(){}
F.prototype=Person.prototype;
Player.prototype=new F();
//子类的原型是空对象,而空对象的原型又是父类


//子类可以重写父类的同名方法,但又不会覆盖父类的同名方法
jordan=new Player('Jordan',50,'basketball');//构造一个子类对象
jordan.show();//此处调用的是子类的show方法
//my name is Jordan,50 years old.
//I am a basketball player.
zhang=new Person('ZhangSan',20);
zhang.show();//此处调用的是父类show方法
//my name is ZhangSan,20 years old.

//子类可以继承父类方法
zhang.hello();
//ZhangSan is saying hello!
jordan.hello();
//Jordan is saying hello!

//子类也可以有自己独有的方法 jordan.play();
//Jordan is playing basketball.
zhang.play();
//undefined is not a function //call和apply方法的第一个参数为调用构造器的对象,后面是要传递的实参,只是apply采用数组的形式。

 

事件和函数绑定

 

var btn1=document.getElementById('btn1');
/*方法一*/
btn1.onclick=function() {
    this.innerHTML='how are you?'
}

/*方法二 事件注册*/
function myAlert() {
    alert('one click only!');
    removeEvent(btn1,'click',myAlert)
}

//w3c
btn1.addEventListener('click',myAlert,false);

//IE
btn1.attachEvent('onclick',myAlert);

//写一个跨浏览器的通用方法
function addEvent (elem,type,fn) {
    if(elem.attachEvent){ //IE
        elem.attachEvent('on'+type,fn);
        return;
    }
    if(elem.addEventListener){ //W3C
        elem.addEventListener(type,fn,false);
    }
}    

//通用调用
addEvent(btn1,'click',myAlert);

 

 

事件解绑

 

//写一个跨浏览器的通用方法--解除绑定
function removeEvent (elem,type,fn) {
    if(elem.detachEvent){
    elem.detachEvent('on'+type,fn);
    return;
    }
    if(elem.removeEventListener){
    elem.removeEventListener(type,fn,false);
    }
}
//写一个跨浏览器的通用方法--事件绑定
function addEvent (elem,type,fn) {
    if(elem.attachEvent){
    elem.attachEvent('on'+type,fn);
    return;
    }
    if(elem.addEventListener){
    elem.addEventListener(type,fn,false);
    }
}

var btn1=document.getElementById('btn1');
//事件处理程序
function myAlert() {
    alert('one click only!');
    removeEvent(btn1,'click',myAlert);//调用一次立即解除绑定,以后再单击就不会执行该事件处理程序
}

addEvent(btn1,'click',myAlert);

 

阻止默认事件

 

//阻止默认行为
function myEventHandler (e) {
    e=e || window.event;
    if(e.preventDefault){
        e.preventDefault();
    }else{
        e.returnValue=false;
    }
}

//事件处理程序
function aHandler (e) {
    myEventHandler(e);
    console.log('you Click a!');
}

//html
<a id="a1" href="http://www.nba.com">Mike</a>

a1=document.getElementById("a1");

//事件绑定
a1.addEventListener('click',aHandler,false);

//这样点击链接后不会跳转到指定的url,只会执行该事件处理程序

 

事件冒泡

//html
<div id="div1">
    <p id="p1">I love <a id="a1" href="">Mike</a>.</p>
</div>

//获取Dom元素
div1
=document.getElementById("div1"); p1=document.getElementById("p1"); a1=document.getElementById("a1");
//阻止默认的事件,避免链接跳转
function myEventHandler (e) { e=e || window.event;//e为w3c标准事件对象,window.event为微软IE的事件对象
  //w3c
if(e.preventDefault){ e.preventDefault();
  //IE }
else{ e.returnValue=false; } } //div的事件处理程序 function divHandler () { console.log('you Click div!'); }
//p的事件处理程序
function pHandler () { console.log('you Click p!'); }
//a的事件处理程序
function aHandler (e) { myEventHandler(e); e=e || window.event; if(e.stopPropagation){ //W3C e.stopPropagation(); }else{ //IE e.cancelBubble=true; } console.log('you Click a!'); } //事件注册 div1.addEventListener('click',divHandler,false); p1.addEventListener('click',pHandler,false); a1.addEventListener('click',aHandler,false);
//如果不阻止事件冒泡,则点击链接后,先触发a的事件,再触发p的事件,最后触发div的事件。
//如果在a的事件中阻止向上冒泡的话,则只会引发a的事件。

 

事件委托

var table1=document.getElementById('table1');
table1.onclick=function(e) {
    e=e || window.event;
    console.log(e);
    var targetNode=e.target || e.srcElement;
    if(targetNode.nodeName.toLowerCase()==='tr'){
        alert('You clicked a table row!');
    }
}
/*如果你有一个很多行的大表格,在每个<tr>上绑定点击事件是个非常危险的想法,因为性能是个大问题。流行的做法是使用事件委托。事件委托描述的是将事件绑定在容器元素上,然后通过判断点击的target子元素的类型来触发相应的事件。
事件委托依赖于事件冒泡,如果事件冒泡到table之前被禁用的话,那上面的代码就无法工作了。*/

 

posted @ 2016-03-24 10:48  框框A  阅读(3642)  评论(0编辑  收藏  举报