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之前被禁用的話,那上面的代碼就無法工作了。*/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM