主頁 > 前端設計 > 關于JavaScript(你所不知道的小秘密)

關于JavaScript(你所不知道的小秘密)

2021-03-07 14:58:22 前端設計

主流瀏覽器的內核

IE:trident
Chrome:webkit/blink
firefox:Gecko
Opera:presto
Safari:webkit

引入JS的方式

頁面內嵌標簽(可在head內或body內)
外部引入(常用方法)

JS基本語法

變數:
變數宣告:宣告,賦值分解,單一var, (var a=100)
命名規則:變數名必須以英文字母,*,$開頭*
變數名可以包括英文字母,,$,數字
不可以用系統的關鍵字,保留字作為變數名


值型別(資料型別):
不可改變的原始值(堆疊資料):Number,Boolean,String,undefined,null
堆疊記憶體和堆疊記憶體之間賦值是拷貝(互不影響)
參考值(堆資料):array,Object,function,..data,RegExp


typeof()可查看資料型別(回傳number,string,boolean,object,undefined,function)
型別轉換:顯式型別轉換:Number(mix) 轉換不了的就顯示為NaN
                   parseInt(string,radix) string以radix進制為基底轉換為10進制
                   parseFloat(string)
                   num.toString(radix) num轉為radix進制
                   String(mix)
                   Boolean()
     隱式型別轉換:isNaN() 先轉為number,再與NaN比較
                   ++/-- +/-(正負)轉為數字型別
                   + 轉為字串
                   - * / %  轉為數字型別 '1'*1=1
                   && || !
                   < > <= >= 字串與數字比較,轉為數字再比較,字串與字串比較,比較ascii碼
                   == != 轉為數字再比較
不發生型別轉換:===,!==


陳述句的基本規則:
每一句后面要以分號結束(除函式,for陳述句,if陳述句...)
js語法錯誤(低級錯誤,邏輯錯誤)會引發后續代碼終止,但不會影響其他js代碼塊
書寫格式要規范,'=+/-'兩邊要有空格

運算運算子:
'+':數學運算,字串連接,
    任何資料型別加字串都等于字串
'-','*','/','%','=','()':'()'優先級最高,'='優先級最低
 '++','--','+=','-=','/=','*=','%='
e.g. var a = 10 ; var b = ++a - 1 + a++ (此時b等于21,a等于12)
 var a = 1 ; var b = a-- + --a (此時b等于0(先算--a,然后b=0+0=0),a等于-1) 

比較運算子:'>','<','==','>=','<=','!='(比較結果為boolean值) NaN!=NaN

邏輯運算子:'&&'(碰到假就停),'||'(碰到真就停),'!'(運算結果為真實的值)
e.g. var a = 1 && 2+2 (a為4)
    var a = 0 && 2+2 (a為0)
    var a = 2+1 && 0 (a為0)
    var a = 1 || 3 (a為1)
    var a = 0 || 2 (a為2)
    (window.foo || (window.foo='bar')) (window.foo的值為bar(先看括號的))

被認定為false的值:undefined,null,NaN,'',0,false

條件陳述句:if,if else if,switch case,break,continue
回圈陳述句:for,while,do while

函式

定義:函式宣告(function xxx(){})
函式運算式(命名函式運算式:var test=function xxx(){}, 匿名函式運算式(常用):var test=function (){})
組成形式:函式名稱(小駝峰原則 如theFirstName)
         引數:形參(獲取形參長度:函式名.length),實參(arguments表示的是實參串列,獲取實參長度:arguments.length)
         回傳值


e.g.1 求5的階乘(遞回)
    function mul(n){
        if(n==1 || n==0)
        {
            return 1
        }
        return n*mul(n-1);
    }
    mul(5);

作用域

作用域定義:變數和函式生效的區域(存盤了運行期背景關系的集合)
作用域的訪問順序:函式里面的可以訪問外面的值(里面的可以訪問外面的,外面的不能訪問里面的)
函式被定義時,會在作用域鏈中生成一個GO物件
函式被執行時,會在作用域鏈中多生成一個AO物件,此時0號位置是AO,1號位置是GO


當多個函式為包含關系時,各函式作用域鏈的變化:
 e.g. function a(){
        function b(){
          function c(){
          }
          c();
        }
      b();
    }
    a();

   a defined  a.[[scope]] --> 0:GO
   a doing  a.[[scope]] --> 0:aAO 1:GO
   b defined  b.[[scope]] --> 0:aAO 1:GO
   b doing  b.[[scope]] --> 0:bAO 1:aAO 2:GO 
   c defined  c.[[scope]] --> 0:bAO 1:aAO 2:GO
   c doing  c.[[scope]] --> 0:cAO 1:bAO 2:aAO 3:GO
   
   with會改變作用域鏈:with(訪問的物件){執行的代碼} 
                      若訪問的物件沒有對應的變數,則在原本執行的這個函式體中找變數,
   e.g.
   var obj={name:'obj'};
   function test(){
        var age=123;
        var name='scope';
        with(obj){
               console.log(name);  //輸出obj
               console.log(age);  //輸出123
        }
   }       

JS三部曲(預編譯重點)

語法分析
預編譯(發生在函式執行的前一刻)
解釋執行


預編譯:函式宣告整體提升
        變數宣告提升
預編譯前奏:imply global暗示全域變數:即任何變數,如果變數未經宣告就賦值,此變數為全域物件(window)所有(var a=b=123(b為經宣告就賦值,歸window所有,所以window.a為undefined,window.b為123))
       一切宣告的全域變數,全是window的屬性(var a=123 => window.a=123)
預編譯程序四部曲:創建AO物件
             找形參和變數宣告,將變數和形參名作為AO屬性名,值為undefined
             將實參值和形參統一
             在函式體里面找函式宣告,值賦予函式體

e.g. function fn(a){                 1.創建AO物件(執行期背景關系)
    console.log(a);               2.找形參和變數宣告
    var a=123;                      AO{a:undefined,b:undefined}
    console.log(a);               3.將實參和形參統一
    function a(){};                 AO{a:1,b:undefined}
    console.log(a);               4. 找函式宣告
    var b=function(){}              AO{a:function a(){},b:undefined,d:function d(){}}
    console.log(b);
    function d(){}
    }
    fn(1)

所以第一個console.log(a)列印的是function a(){}
 此時執行var a=123,所以此時AO{a:123,b:undefined,d:function d(){}}
第二個console.log(a)列印的是123
此時不用再看function a(){}(因為預編譯已經看過了)
第三個console.log(a)列印的是123
此時執行var b=function (){},所以此時AO{a:123,b:function (){},d:function d(){}}
第四個console.log(b)列印的是function (){}

若一個變數未經宣告就賦值,會把此變數放到GO物件(window)中

e.g.1 console.log(test);
   function test(test){
    console.log(test);
    var test=234;
    console.log(test);
    function test(){};
   }
   test(1);
   var test=123;

   先創建GO物件:GO{test:function (){...}}
   再創建AO物件:AO{test:function (){}}

   所以第一個console.log(test)為function(){}
   第二個為function(){}
   執行var test=234,所以AO{test:234}
   第三個為234

   e.g.2 global=100;
         function fn(){
         console.log(global);
         global=200;
         console.log(global);
         var global=300;
         }
         fn();
         var global;

         先創建GO:{global:100}
         再創建AO:{global:undefined}
         此時第一個輸出為undefined(AO中有的就先從AO中找)
         再執行global=200;此時AO:{global:200}
         所以第二個輸出為200

  e.g.3 function test(){
            console.log(b);
            if(a){
                var b=100;
                }
                console.log(b);
                c=234;
                console.log(c);
                }
                var a;
                test();
                a=10;
                console.log(c);

                先創建GO:{a:undefined}
                再創建AO:{b:undefined}
                第一個輸出為undefined
                此時a為undefined,不能執行var b=100
                所以第二個輸出為undefined
                執行c=234,AO里沒有c,則把變數c添加到GO中,此時GO{a:undefined,c:234}
                第三個輸出為234
                再執行a=10,此時GO{a:10,c:234}
                第四個輸出為234

 e.g.4 var x=1;
       if(function f(){}){
          x+=typeof f;
       }
       console.log(x);

       因為(function f(){})為運算式,所以f是undefined
       所以x輸出為1undefined
       (未經宣告的變數放在typeof中不會報錯,為undefined)


   關于GO和AO物件,若AO上沒有相應變數,則再去GO上找
   預編譯時會忽略掉判斷的陳述句
   GO和AO物件實則是執行期背景關系

立即執行函式

立即執行函式主要針對初始化功能的函式(執行完就被銷毀)
(function (形參(可有可無)){}(實參(可有可無)))
只有運算式才能被執行符號執行
如:var test=function (){}();
    +function test(){}();
    (function test(){})();

閉包(重點)

閉包的生成:當內部函式被保存到外部的時候
閉包的防范:閉包會導致多個執行函式共用一個公有變數,如果不是特殊需要,應盡量防止這種情況發生
閉包的作用:實作公有變數(函式累加器)
           可以做快取(存盤結構)
           可以實作封裝,屬性私有化
           模塊化開發,防止污染全域變數
可用立即執行函式解決閉包

e.g. 給4個li系結點擊事件
    var li=document.getElementByTagName('li');
     for(var i=0;i<li.length;i++){
            (function (j){
                li[j].onclick=function(){
                console.log(j)
            }(i))
    }

物件

屬性的增,刪,改,查:
增:物件名.屬性名=屬性值
刪:delete 物件名.要洗掉的屬性名
改:物件名.要修改的屬性名=新的屬性值
查:物件名.要查看的屬性名

物件的創建方法:
1. 物件字面量/物件直接量 var obj={}
2. 建構式(大駝峰命名規則:如TheFirstName):系統自帶的建構式Object():var obj=new Object()
                                             自定義:function 函式名(){this.屬性名=屬性值...}
                                                    var 物件名= new 函式名()
3. var obj=Object.create(原型/null)(創建物件的同時可自定義原型)

改造函式的內部原理:1.在函式體最前面隱式的加上this={}(AO:{this:{xxx}})
                   2.執行this.xxx=xxx
                   3.隱式的回傳this(建構式中回傳值不能回傳原始值,會忽略掉,自動回傳this)
 
 包裝類:new String()
         new Boolean()
         new Number()
 e.g. var str='abc';
      str+=1;
      var test=typeof(str);
      if(test.length==6){
            test.sign='typeof的回傳結果可能為String';
            (原始值賦屬性值要呼叫包裝類,賦和沒賦一樣)
            //new String(test).sign='xxx' 隨后delete
       }
       //new String(test).sign(為undefined)
       cosnole.log(test.sign);
        輸出的結果為undefined

原型

原型是function物件的一個屬性,它定義了建構式制造出來的物件的公共祖先
通過該建構式產生的物件,可以繼承該原型的屬性和方法
原型也是物件
利用原型可以提取公有的屬性
物件查看原型:隱式屬性__proto__  (函式名.prototype)
物件查看物件的建構式:constructor
判斷是否為自身的屬性:物件名.hasOwnProperty(屬性值)

e.g. Person.prototype.name='sunny'
     function Preson(){}
     var person=new Preson();
     Preson.prototype.name='cherry';
     此時 person.name='cherry'
     
     Person.prototype.name='sunny'
     function Preson(){}
     var person=new Preson();
     Preson.prototype.name={name:'cherry'}
     類似于
     var obj={name:'a'};
     var obj1=obj;
     obj={name:'b'};(新開的空間)
     所以此時 person.name還是等于'sunny'(此時的__proto__還是指向原來的Person.prototype)

原型鏈中絕大多數物件最終都會繼承自Object.prototype

undefined和null沒有原型

改變this指向:call,apply
call:原來的函式名.call(this要指向的函式名,引數)
apply:原來的函式名.apply(this要指向的函式名,[引數])

call和apply的區別:傳引數的形式不同
                   call是要把實參按照形參的個數傳進去
                   apply是傳一個arguments

繼承模式

1. 傳統形式(原型鏈):過多的繼承了沒用的屬性
2. 借用建構式:不能繼承借用建構式的原型
                每次建構式都要多走一個函式
3. 共享原型:不能隨便改動自己的原型
4. 圣杯模式
   第一種寫法:
   function inherit(Target,Origin){
        function F(){};
        F.prototype=Origin.prototype;
        Target.prototype=F.prototype;
        Target.prototype.constructor=Target;
        Target.prototype.uber=Origin.prototype;
    }
   第二種寫法:
   var inherit=(function (){
        var F=function (){};
        return function(Target,Origin){
             F.prototype=Origin.prototype;
             Target.prototype=F.prototype;
             Target.prototype.constructor=Target;
             Target.prototype.uber=Origin.prototype;
        }
   }())

命名空間

管理變數,防止污染全域,適用于模塊化開發

可使用閉包的方法實作變數私有化,從而防止變數污染
var name='bcd';
var init=(function (){
    var name='abc';
    function callName(){
        console.log(name);
    }
    return function(){
        callName();
    }
}())
init();
此時列印出來的name還是abc

還可使用Webpack等

JS實作鏈式呼叫模式(仿JQ)

如:obj.eat().smoke().drink()

在每個方法后面return this

物件列舉

陣列遍歷:for回圈陣列長度

物件遍歷:for in回圈
for(var xxx(自定義) in 物件名){console.log(物件名[xxx])}

區分陣列,物件的三種方法

方法一:instanceof
判斷A物件是不是B建構式構造出來的(判斷A物件的原型鏈上有沒有B的原型):A instanceof B
陣列:[] instanceof Array --> true 
物件:{} instanceof Object --> true

方法二:constructor
物件:obj={},obj.constructor --> function Object()
陣列:arr=[],arr.constructor --> function Array()

方法三:toString()
陣列:Object.prototype.toString.call([]) --> [object Array]
物件:Object.prototype.toString.call([]) --> [object Object]

關于this

函式預編譯程序 this -> window
全域作用域里 this -> window
call/apply可改變函式運行時的指向
obj.func();   func()里面的this指向obj(誰呼叫this指向誰)

e.g.1 var name='222';
     var a={
        name:'111',
        say:function(){
            console.log(this.name);
         }
      }
      var fun=a.say;
      fun();  //全域呼叫
      a.say(); //a呼叫
      var b={
          name:'333',
          say:function(fun){
                fun();
          }
       }
       b.say(a.say);  //沒有說明是this呼叫,只是把a.say這個方法傳進來執行(相當于借用這個方法在b里面執行),此時還是全域呼叫
       b.say=a.say;
       b.say();  //此時為b呼叫
       
       依次的輸出結果為:222,111,222,333
  
 e.g.2 var foo=123;
        function print(){
            this.foo=234;
            console.log(foo);
        }
        print();
        
        執行this.foo=234時,此時this指向window,改變GO中foo的值為234
        所以輸出結果為234
        
  若把上題的print()改為new print():由于此時的this=Object.create(print.prototype),this不指向window了
  所以此時輸出結果為123
  
  e.g.3 var a=5;
        function test(){
            a=0;
            alert(a);
            alert(this.a);
            var a;
            alert(a);
        }
        test();  依次輸出0 5 0
        new test(); 依次輸出0 undefined(this上面沒有a) 0
        
  e.g.4 var bar={a:'002'};
        function print(){
            bar.a='a';
            Object.prototype.b='b';
            return function inner(){
            console.log(bar.a);
            console.log(bar.b);
            }
        }
        print()();(相當于先回傳一個函式,再進行函式執行)  依次輸出為a,b
        
       
arguments.callee:會指向自己的參考,參考該函式的函式體內的當前正在執行的函式,當函式名稱未知時,例如在沒有名稱的函式運算式中(也稱為“匿名函式”),此功能很有用,
e.g. var num=(function(n){
        if(n==1){
            return 1
         }
         return n * arguments.callee(n-1)
     }(100))
                    
 func.caller:回傳呼叫指定函式的函式
 
 注意:arguments.callee和func.caller在嚴格模式下都不能使用

克隆

 淺層克隆和深層克隆的區別:
 淺層克隆:當克隆參考值時,兩個物件會共用一個參考地址,造成相互的干擾,即我改,它也改
 深層克隆:克隆出來的物件和原來的物件是相互獨立的,互不影響,也就是對新物件的修改都不會反映到原物件中
    
 淺層克隆:
    function clone(origin,target){
        var target=target || {};
        for(var prop in origin){
            target[prop]=origin[prop];
          }
          return target;
     }

 深層克隆:
 	實作步驟:
    1. 判斷是不是原始值 (typeof)
    2. 判斷是陣列還是物件(instanceof,toString(推薦使用),constructor)
    3. 建立相應的陣列或物件
    4. 遞回
    function deepClone(origin,target){
            var target=target || {};
            var toStr=Object.prototype.toString;
            var arrStr="[object Array]";
            for(var prop in origin){
                   if(origin.hasOwnProperty(prop)){  //要克隆自身的屬性
                        if(origin[prop] !== "null" && typeof(origin[prop])=='object'){
                             if(toStr.call(origin[prop])==arrStr){ //克隆的屬性是個陣列 
                                 target[prop]=[];  //新建一個陣列
                             }
                             else{  //克隆的屬性是個物件
                                 target[prop]={};   //新建一個物件
                             }
                            deepClone(origin[prop],target[prop]) 
                        }
                        else{  //原始值直接拷貝
                            target[prop]=origin[prop];
                        } 
             }    
        }

陣列和類陣列

創建陣列的方法:
var arr=[];
var arr=new Array(1,2,3,4);
var arr=new Array(10);  
new Array():當為一個引數n時表示新開一個長度為n的陣列空間
             當為多個引數時表示陣列里的值
  
 陣列的讀和寫:
 arr[n]:讀,但不可以溢位讀,要不然結果為undefined
 arr[n]=xxx:寫,可以溢位寫
 
 陣列常用的方法:
 會改變原陣列的:push(在陣列末尾添加資料)
                pop(剪切陣列末尾的資料)
                shift(剪切陣列前面的資料)
                unshift(在陣列前面添加資料)
                sort(資料排序,默認升序):arr.sort(function(a,b){return x(若x為負數時,那么前面的數放在前面,若x為正數,那么后面的數放在前面,若x為0,則不動,可直接利用return a-b進行升序,return b-a進行降序)})
                                          可利用sort生成一個亂序陣列:xxx.sort(function(){ return Math.random()-0.5 })
                reverse(資料反轉倒序)
                splice(切片):splice(從第幾位開始,截取多少長度,在切口處添加新的資料)
 不會改變原陣列的:concat(陣列拼接)
                  join(連接):join('x')按照'x'來連接陣列里的資料
                  split(拆分):solit('x')按照'x'來拆分陣列里的資料,拆分為字串
                  toString(變成字串)
                  slice(截取):slice(從該位開始截取,截取到該位)
               
  
 類陣列:
 可以利用屬性名模擬陣列的特性
 可以動態的增長length屬性
 如果強行讓類陣列呼叫push方法,則會根據length屬性值的位置進行屬性的擴充
 屬性要為索引(數字)屬性,必須有length屬性,最好加上push  
 e.g. var obj={
        "2" : "a",
        "3" : "b",
        "length" : 2,
        "push" : Array.prototype.push
        }
        obj.push('c'); 
        obj.push('d');
        輸出結果obj
        
       push的原理是:
       Array.prototype.push=function(target){
            this[this.length]=target;
            this.length++;
       }
       所以obj.push('c'),在這個obj中相當于obj[obj.length(即為2)]='c',然后再length++
       隨后obj.push('d'),相當于obj[3]='d'
       所以輸出的obj為{
                        "2" : "c",
                        "3" : "d",
                        "length" : 2,
                        "push" : Array.prototype.push
                      }
        
        
 實作陣列的去重(在原型鏈上實作):
 Array.prototype.unique=function(){
        var temp={};
        var arr=[];  //放置去重完后的陣列
        var len=this.length;
        for(var i=0;i<len;i++){
               if(!temp[this[i]]){  //若沒有對應的屬性值
                      temp[this[i]]='abc';
                      arr.push(this[i]);
                }
       }
     return arr;  
 }

Try…catch

在try里面的發生錯誤,不會執行錯誤后的try里面的代碼,但還會依然執行外面的代碼
try{

}catch(e){

}

常見的錯誤資訊(error.name的六種對應資訊):
1. EvalError:eval()的使用與定義不一致
2. RangeError:數值越界
3. ReferenceError:非法或不能識別的參考數值
4. SyntaxError:發生語法決議錯誤
5. TypeError:運算元型別錯誤
6. URLError:URL處理函式使用不當  

es5嚴格模式

"use strict"(要寫在頁面邏輯的最頂端)
不再兼容es3的一些不規則語法,使用全新的es5規范,
兩種用法:全域嚴格模式
         區域函式內嚴格模式(推薦)
"use strict"就是一行字串,不會對不兼容嚴格模式的瀏覽器產生影響,
不支持with,arguments,callee,func,caller,變數賦值前必須宣告,區域this必須被賦值(Person.call(null/undefined)賦值什么就是什么),拒絕重復屬性和引數

DOM操作

DOM定義了表示和修改檔案所需的方法,DOM物件即為宿主物件,由瀏覽器廠商定義,用來操作html和xml功能的一類物件的集合,

對節點的增刪改查
查: (除了getElementsById匹配出來是一個,其他匹配出來都是類陣列(要在末尾加上[n(0,1,2,...)]))
     document.getElementById('id名') 根據元素id匹配相應的元素(在IE8以下的瀏覽器不區分id名大小寫)
     document.getElementsByTagName('標簽名') 根據元素標簽名匹配相應的元素
     document.getElementsByName('name名') 根據元素的標簽name匹配相應的元素
     document.getElementsByClassName('類名') 根據元素標簽名匹配相應的元素(在IE8和IE8以下的瀏覽器沒有,可以多個class一起)
     document.querySelector('CSS選擇器字串') 匹配指定 CSS 選擇器的一個元素(在IE7和IE7以下的版本沒有)不能實時更新
     document.querySelectorAll('CSS選擇器字串') 匹配指定 CSS 選擇器的一組元素(在IE7和IE7以下的版本沒有)不能實時更新
增:
    document.createElement():創建元素節點
    document.createTextNode():創建文本節點
    document.createComment():創建注釋節點
    document.createDocumentFragment():創建虛擬的節點物件(可在其中添加DOM節點以構建螢屏外DOM樹)
插:
    要添加到的區域.appendChild(要添加的節點):從后面添加一個子節點到頁面(是一種剪切操作)
    要添加到的區域.insertBefore(要添加的節點,要在此節點前添加的節點):從前面添加一個子節點到頁面
    封裝函式insertAfter():
    Element.prototype.insertAfter(targetNode,afterNode){
        var beforeNode=afterNode.nextElementSibling;
        if(beforeNode==null){  //若是最后一個節點,則直接在其后面插入
            this.appendChild(targetNode);
        }
        else{   //在要插的下一個節點前插入(相當于插在要插節點的后面)
            this.insertBefort(targetNode,beforeNode);
       }
    }
刪:
    父節點.removeChild():父節點移除子節點(剪切操作)
    節點.remove():節點自己移除自己(洗掉操作)
替換:
    父節點.replaceChild(new,origin):替換子節點
       
遍歷節點樹:
parentNode:父節點(最頂端的parentNode為#document)
childNodes:子節點們
firstChild:第一個子節點
lastChild:最后一個子節點
nextSibling:后一個兄弟節點
previousSibling:前一個兄弟節點

節點的型別:元素節點(1)
           屬性節點(2)
           文本節點(3)
           注釋節點(8)
           document(9)
           DocumentFragment(11)
           
基于元素節點樹的遍歷:
parentElement:回傳當前元素的父元素節點(IE不兼容)
children:只回傳當前元素的元素子節點
node.childElementCount(相當于node.children.length):回傳當前元素節點的子元素個數
firstElementChild:回傳第一個元素節點(IE不兼容)
lastElementChild:回傳最后一個元素節點(IE不兼容) 
nextElementSibling:回傳后一個兄弟元素節點
previousElementSibling:回傳前一個兄弟元素節點
(IE不兼容都是指IE9和IE9以下瀏覽器不兼容)

節點的四個屬性:
nodeName:元素的標簽名,以大寫形式表示,只讀
nodeValue:Text節點或Comment節點的文本內容,可讀寫
nodeType:該節點的型別,只讀
attribute:Element節點的屬性集合

節點的一個方法:Node.hasChildNodes()(判斷是否有子節點)

Element節點的一些屬性:
innerHTML:添加HTML結構內容
innerText/textContent:添加文本結構內容(innerText 火狐不兼容,textContent IE老版本不好使)

Element節點的一些方法:
ele.setAttribute(屬性名,屬性值):設定節點屬性
ele.getAttribute(屬性名):獲取節點屬性

date(日期)物件

系統提供的
var date=new Date();
詳細功能方法可參考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date

定時器 , 延時器

設定定時器:
定時器名=setInterval(function(){
      .....
},1000)

清除定時器:
clearInterval(定時器名)

設定延時器:
延時器名=setTimeout(function(){
    .....
},1000)  //時間間隔在window系統里面最小是15ms,在MAC系統里面最小是10ms(即使設定為0,也會按照最小的時間間隔執行)

清除延時器:
clearInterval(延時器名)

關于setTimeout和setInterval的最小值,詳細可參考網址:https://www.cnblogs.com/daysme/p/6207495.html

獲取視窗屬性,dom尺寸

查看滾動條的滾動距離:
window.pageXOffset/pageYOffset(橫向/縱向) (IE8/IE8以下不兼容)
document.body/documentElement.scrollLeft/scrollTop (兼容性混亂)
(使用的時候可兩者相融合(相加),適應兼容性)
如:document.body.scrollLeft+document.documentElement.scrollLeft

封裝兼容性方法:getScrollOffset(){
                    if(0 && window.pageXOffset){
                        return{
                            x:window.pageXOffset,
                            y:window.pageYOffset
                        }
                     }  
                     else{
                         return{
                            x:document.body.scrollLeft+document.documentElement.scrollLeft,
                            y:document.body.scrollTop+document.documentElement.scrollTop
                         }
                     }
               }
       
       
查看視口的尺寸:
window.innerWidth/innerHeight(查看視窗的寬高)(IE8/IE8以下不兼容)
document.documentElement.clientWidth/clientHeight(標準模式下任何瀏覽器兼容)
document.body.clientWidth/clientHeight(適用于怪異模式下的瀏覽器)
判斷是否為怪異模式:document.compatMode:CSS1Compat(正常模式),backCompat(怪異模式)

封裝兼容性方法:getViewportOffset(){
                    if(0 && window.innerWidth){
                        return {
                            w:window.innerWidth,
                            h:window.innerHeight
                        }
                    }
                    else{
                        if(document.compatMode==='BackCompat'){  //怪異模式下
                            return {
                                w:document.body.clientWidth,
                                h:document.body.clientHeight
                            }
                        }
                        else{
                            return {
                                w:document.documentElement.clientWidth,
                                h:document.documentElement.clientHeight,
                            }
                        }
                    }
              }


查看元素的幾何尺寸:domEle.getBoundingClientRect()
                   回傳一個物件,包含left,top,right,bottom,width,height等屬性(但width,height在IE老版本中沒有顯示)
                   回傳結果不實時
                
查看元素的尺寸:dom.offsetWidth,dom.offsetHeight
查看元素的位置:dom.offsetLeft,dom.offsetTop
               dom.offsetParent(回傳最近的有定位的父級,若無則回傳body,body.offsetParent回傳null)
               
封裝函式:getElementPosition(求相對于檔案的坐標)

使滾動條滾動的三個方法:scroll(x,y):滾動到...
                      scrollTo(x,y):滾動到...
                      scrollBy(x,y):滾動了...(會累加)

腳本化CSS

讀寫元素css屬性:
dom.style.prop
可讀寫行間樣式,沒有兼容性問題,碰到float這樣的保留字屬性,前面應加css(即float --> cssFloat)
復合屬性盡量拆解
組合單詞變成小駝峰式寫法

查詢計算樣式:
window.getComputedStyle(ele,null)[prop]
計算樣式只讀
回傳的計算樣式的值都是絕對值,沒有相對單位
IE8及IE8以下不兼容 
null用在獲取偽元素時,改變null(如:window.getComputedStyle(ele,'after').width)

查詢樣式(IE8及IE8以下可用,IE獨有):ele.currentStyle.prop
計算樣式只讀
回傳的計算樣式的值不是經過轉換的絕對值

封裝兼容性方法:getStyle(ele,prop){
                    if(window.getComputedStyle){
                        return window.getComputedStyle(ele,null)[prop]; 
                    }
                    else{
                        return ele.currentStyle.prop;
                    }
                }

事件

 系結事處理函式:
 ele.onxxx=function(e){} 兼容性很好,但是一個元素的同一個時間上只能系結一個處理程式  this指向元素本身
 obj.addEventListener(type,fn,false){} IE9以下不兼容,可為一個事件系結多個處理程式  this指向元素本身
 obj.attachEvent('on'+type,fn){} IE獨有,一個事件同樣可以系結多個處理程式  this指向window
 
 封裝兼容性的函式方法:addEvent(ele,type,handle){
                        if(ele.addEventListener){
                            ele.addEventListener(type,handle,false);
                        }
                        else if(ele.attachEvent){
                            ele.attachEvent('on'+type,function(){
                                handle.call(ele);
                            })     
                        }
                        else{
                            ele['on'+type]=handle;
                        }
                     }
                     
解除事件處理函式:
ele.onclick=false/null/''
ele.removeEventListener(type,fn,false)
ele.detachEvent('on'+type,fn)
 
事件處理模型:
事件冒泡:結構上(非視覺上)嵌套關系的元素,會存在事件冒泡的功能,即同一事件,自子元素冒泡向父元素(自底向上)
(focus,blur,change,submit,reset,selectd等事件不冒泡)
取消冒泡事件發生:e.stopPropagation()(不支持IE9以下的版本)
                 e.cancelBubble=true(IE獨有)

事件捕獲:結構上(非視覺上)嵌套的關系的元素,會存在事件捕獲的功能,即同一事件,自父元素捕獲至子元素(事件源元素) (自頂向下) IE沒有捕獲事件
把addEventlistener中第三個引數改為true可觸發事件捕獲

觸發順序:先捕獲后冒泡

阻止默認事件(表單提交,a標簽跳轉,右鍵選單等):
return false:以物件屬性的方式注冊的事件才生效
e.preventDefault() (IE9以下不兼容)
e.returnValue=false (兼容IE9)

事件物件:
event(非IE瀏覽器都有) || window.event(用于IE瀏覽器)

事件源物件:
event.target (火狐只有這個)
event.srcElement (IE只有這個)
上面兩種chrome都有

事件委托:
利用事件冒泡和事件源物件進行處理
優點:性能不需要回圈所有的元素一個個系結事件
      靈活,當有新的元素時不需要重新系結事件
      
事件分類:
滑鼠事件:click,mousedown,mousemove,mouseup,contextmenu,mouseover,mouseout,mouseenter,mouseleave
event中的button屬性可區分滑鼠按鍵(左鍵為0,右鍵為2)

鍵盤事件:keydown,keyup,keypress(keydown > keypress > keyup)
keydown和keypress的區別:keydown可回應任意鍵盤按鍵
                        keypress只回應字符類鍵盤按鍵,可回傳ASCII碼并轉換成相應字符
                        
文本操作事件:input(實時獲取文本的值),focus,blur,change(失焦后才獲取文本的值)

表單操作類(window上的事件):scroll,load

JSON

一種傳輸資料的格式(以物件為樣板,本質上是物件,但用途有區別,物件就是本地用的,json是用來傳輸的)
JSON中,屬性名必須帶雙引號
JSON.parse():string -> json
JSON.stringfy():json -> string

異步加載js

js加載的缺點:加載工具方法沒必要阻塞檔案,使得js加載會影響頁面效率,一旦網速不好,那么整個網站將等待js加載而不進行后續渲染等作業

js異步加載的三種方案:
1. defer異步加載,等到dom檔案全部決議完才會被執行,只有IE能用,也可將代碼寫到內部,
2. async異步加載,加載完就執行,async只能加載外部腳本,不能把js寫在script標簽里
3. 創建script,插入到DOM中,加載完畢后callback
(其中第一和第二個方法執行時也不阻塞頁面)

js加載的時間線

1. 創建Document物件,開始決議web頁面,決議HTML元素和他們的文本內容后添加Element物件和Text節點到檔案中, (document.readyState='loading')
2. 遇到link外部css,創建執行緒加載,并繼續決議檔案
3. 遇到script外部js,并且沒有設定async,defer,瀏覽器加載,并阻塞,等待js加載完成并執行該腳本,然后繼續決議檔案
4. 遇到script外部js,并且設定有async,defer,瀏覽器創建執行緒加載,并繼續決議檔案,對于async屬性的腳本,腳本加載完成后立即執行,(異步禁止使用document.write())
5. 遇到img等,先正常決議dom結構,然后瀏覽器異步加載src,并繼續決議檔案
6. 當檔案決議完成,document.readyState='interactive'
7. 檔案決議完成后,所有設定有defer的腳本會按照順序執行
8. document物件觸發DOMContentLoaded事件,標志著程式執行從同步腳本執行階段,轉化為事件驅動階段
9. 當所有async的腳本加載完成并執行后,img等加載完成后,document.readyState='complete',window物件觸發load

正則運算式

轉義字符:'\'
/^開頭,結尾$/
正則運算式作用:匹配特殊字符或有特殊搭配原則的字符的最佳選擇

兩種創建方式:直接量(推薦):var reg=/.../(后面可加i(忽略大小寫)/g(全域匹配)/m(多行匹配))
             new RegExp():var reg=new RegExp('...','i/g/m')
             
正則運算式上的方法:reg.test(str)(檢索字串中指定的值,回傳 true 或 false)
                   reg.exec(str)(檢索字串中指定的值,回傳找到的值,并確定其位置)
                   ...
                   
支持正則運算式的string物件的方法:str.match(reg)(在字串內檢索指定的值,或找到一個或多個正則運算式的匹配)
                                str.search(reg)(檢索與正則運算式相匹配的值,回傳str中第一個與 reg相匹配的子串的起始位置,若沒有找到任何匹配的子串,則返-1)
                                str.replace(reg/str,replacement)(用一些字符替換另一些字符,或替換一個與正則運算式匹配的子串)
                                ...

正則運算式中一些元字符對應的運算式:\w===[0-9A-z_],\W===[^\w]
                                  \d===[0-9],\D===[^\d]
                                  \s===[\t\n\r\v\f],\S===[^\s]
                                  \b===單詞邊界,\B===非單詞邊界
                                  .===[^\r\n]
                                  
正則運算式的一些量詞:n+(出現一次到多次)
                     n*(出現0次到多次)
                     n?(出現0到1次)
                     n{x}(出現x次)
                     n{x,y}(出現x到y次)
                     以上量詞遵循貪婪匹配原則(盡可能匹配多的)
 
正向預查(從左到右進行匹配):?=xxx(匹配后面跟著xxx的東西)
                            ?!xxx(匹配后面不跟著xxx的東西)
負向預查(從右到左進行匹配):?<=xxx(匹配緊跟xxx后面的東西)
                            ?<!xxx(不匹配緊跟xxx后面的東西)
                     
e.g.1 檢驗一個字串首尾是否含有數字
        var reg=/^\d|\d$/g;
        var str='123abc';
        reg.test(str) -> true
        
e.g.2 檢驗一個字串首尾是否都含有數字
        var reg=/^\d[\s\S]*\d$/g;
        var str='123abc123';
        reg.test(str) -> true
 
 e.g.3 輸出以下replace后的結果
        var str='aa'; //var reg=/a/;
        console.log(str.replace('a'/reg,'b'))
        結果為ba(一般情況下只匹配到一個)
        
        var reg=/a/g;
        console.log(str.replace(reg,'b'))
        結果為bb(全域匹配可匹配多個)
    
 e.g.4 把aabb轉成bbaa
        var reg=/(\w)\1(\w)\2/g;
        var str='aabb';
        console.log(str.replace(reg,'$2$2$1$1'));
        或:console.log(str.replace(reg,function($,$1,$2){
                return $2+$2+$1+$1
            }));
 
 e.g.5 把一串數字用科學計數法表示(從右往左,每三個數打一個點)
        var str='10000000000';
        var reg=/(?=(\B)(\d{3})+$)/g;
        str.replace(reg,'.');
 
詳情可參考網址:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp
               或https://www.w3school.com.cn/jsref/jsref_obj_regexp.asp

一些雜碎

一旦經歷了var的操作,所得出的window上的屬性,這種屬性叫做不可配置的屬性,delete不掉
undefined和null不與數字比較
typeof(arguments):object
document.documentElement等于html
在正則運算式中,加上?可打破貪婪匹配

轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/267138.html

標籤:其他

上一篇:HTML5快速上手筆記--------------------------持續更新

下一篇:父子組件的傳值

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • vue移動端上拉加載

    可能做得過于簡單或者比較low,請各位大佬留情,一起探討技術 ......

    uj5u.com 2020-09-10 04:38:07 more
  • 優美網站首頁,頂部多層導航

    一個個人用的瀏覽器首頁,可以把一下常用的網站放在這里,平常打開會比較方便。 第一步,HTML代碼 <script src=https://www.cnblogs.com/szharf/p/"js/jquery-3.4.1.min.js"></script> <div id="navigate"> <ul> <li class="labels labels_1"> ......

    uj5u.com 2020-09-10 04:38:47 more
  • 頁面為要加<!DOCTYPE html>

    最近因為寫一個js函式,需要用到$(window).height(); 由于手寫demo的時候,過于自信,其實對前端方面的認識也不夠體系,用文本檔案直接敲出來的html代碼,第一行沒有加上<!DOCTYPE html> 導致了$(window).height();的結果直接是整個document的高 ......

    uj5u.com 2020-09-10 04:38:52 more
  • WordPress網站程式手動升級要做好資料備份

    WordPress博客網站程式在進行升級前,必須要做好網站資料的備份,這個問題良家佐言是遇見過的;在剛開始接觸WordPress博客程式的時候,因為升級問題和博客網站的修改的一些嘗試,良家佐言是吃盡了苦頭。因為購買的是西部數碼的空間和域名,每當佐言把自己的WordPress博客網站搞到一塌糊涂的時候 ......

    uj5u.com 2020-09-10 04:39:30 more
  • WordPress程式不能升級為5.4.2版本的原因

    WordPress是一款個人博客系統,受到英文博客愛好者和中文博客愛好者的追捧,并逐步演化成一款內容管理系統軟體;它是使用PHP語言和MySQL資料庫開發的,用戶可以在支持PHP和MySQL資料庫的服務器上使用自己的博客。每一次WordPress程式的更新,就會牽動無數WordPress愛好者的心, ......

    uj5u.com 2020-09-10 04:39:49 more
  • 使用CSS3的偽元素進行首字母下沉和首行改變樣式

    網頁中常見的一種效果,首字改變樣式或者首行改變樣式,效果如下圖。 代碼: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, ......

    uj5u.com 2020-09-10 04:40:09 more
  • 關于a標簽的講解

    什么是a標簽? <a> 標簽定義超鏈接,用于從一個頁面鏈接到另一個頁面。 <a> 元素最重要的屬性是 href 屬性,它指定鏈接的目標。 a標簽的語法格式:<a href=https://www.cnblogs.com/summerxbc/p/"指定要跳轉的目標界面的鏈接">需要展示給用戶看見的內容</a> a標簽 在所有瀏覽器中,鏈接的默認外觀如下: 未被訪問的鏈接帶 ......

    uj5u.com 2020-09-10 04:40:11 more
  • 前端輪播圖

    在需要輪播的頁面是引入swiper.min.js和swiper.min.css swiper.min.js地址: 鏈接:https://pan.baidu.com/s/15Uh516YHa4CV3X-RyjEIWw 提取碼:4aks swiper.min.css地址 鏈接:https://pan.b ......

    uj5u.com 2020-09-10 04:40:13 more
  • 如何設定html中的背景圖片(全屏顯示,且不拉伸)

    1 <style>2 body{background-image:url(https://uploadbeta.com/api/pictures/random/?key=BingEverydayWallpaperPicture); 3 background-size:cover;background ......

    uj5u.com 2020-09-10 04:40:16 more
  • Java學習——HTML詳解(上)

    HTML詳解 初識HTML Hyper Text Markup Language(超文本標記語言) 1 <!--DOCTYPE:告訴瀏覽器我們要使用什么規范--> 2 <!DOCTYPE html> 3 <html lang="en"> 4 <head> 5 <!--meta 描述性的標簽,描述一些 ......

    uj5u.com 2020-09-10 04:40:33 more
最新发布
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 07:59:23 more
  • 生產事故-走近科學之消失的JWT

    入職多年,面對生產環境,盡管都是小心翼翼,慎之又慎,還是難免捅出簍子。輕則滿頭大汗,面紅耳赤。重則系統停擺,損失資金。每一個生產事故的背后,都是寶貴的經驗和教訓,都是專案成員的血淚史。為了更好地防范和遏制今后的各類事故,特開此專題,長期更新和記錄大大小小的各類事故。有些是親身經歷,有些是經人耳傳口授 ......

    uj5u.com 2023-04-18 07:55:04 more
  • 記錄--Canvas實作打飛字游戲

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 打開游戲界面,看到一個畫面簡潔、卻又富有挑戰性的游戲。螢屏上,有一個白色的矩形框,里面不斷下落著各種單詞,而我需要迅速地輸入這些單詞。如果我輸入的單詞與螢屏上的單詞匹配,那么我就可以獲得得分;如果我輸入的單詞錯誤或者時間過長,那么我就會輸 ......

    uj5u.com 2023-04-04 08:35:30 more
  • 了解 HTTP 看這一篇就夠

    在學習網路之前,了解它的歷史能夠幫助我們明白為何它會發展為如今這個樣子,引發探究網路的興趣。下面的這張圖片就展示了“互聯網”誕生至今的發展歷程。 ......

    uj5u.com 2023-03-16 11:00:15 more
  • 藍牙-低功耗中心設備

    //11.開啟藍牙配接器 openBluetoothAdapter //21.開始搜索藍牙設備 startBluetoothDevicesDiscovery //31.開啟監聽搜索藍牙設備 onBluetoothDeviceFound //30.停止監聽搜索藍牙設備 offBluetoothDevi ......

    uj5u.com 2023-03-15 09:06:45 more
  • canvas畫板(滑鼠和觸摸)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>canves</title> <style> #canvas { cursor:url(../images/pen.png),crosshair; } #canvasdiv{ bo ......

    uj5u.com 2023-02-15 08:56:31 more
  • 手機端H5 實作自定義拍照界面

    手機端 H5 實作自定義拍照界面也可以使用 MediaDevices API 和 <video> 標簽來實作,和在桌面端做法基本一致。 首先,使用 MediaDevices.getUserMedia() 方法獲取攝像頭媒體流,并將其傳遞給 <video> 標簽進行渲染。 接著,使用 HTML 的 < ......

    uj5u.com 2023-01-12 07:58:22 more
  • 記錄--短視頻滑動播放在 H5 下的實作

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 短視頻已經無數不在了,但是主體還是使用 app 來承載的。本文講述 H5 如何實作 app 的視頻滑動體驗。 無聲勝有聲,一圖頂百辯,且看下圖: 網址鏈接(需在微信或者手Q中瀏覽) 從上圖可以看到,我們主要實作的功能也是本文要講解的有: ......

    uj5u.com 2023-01-04 07:29:05 more
  • 一文讀懂 HTTP/1 HTTP/2 HTTP/3

    從 1989 年萬維網(www)誕生,HTTP(HyperText Transfer Protocol)經歷了眾多版本迭代,WebSocket 也在期間萌芽。1991 年 HTTP0.9 被發明。1996 年出現了 HTTP1.0。2015 年 HTTP2 正式發布。2020 年 HTTP3 或能正... ......

    uj5u.com 2022-12-24 06:56:02 more
  • 【HTML基礎篇002】HTML之form表單超詳解

    ??一、form表單是什么

    ??二、form表單的屬性

    ??三、input中的各種Type屬性值

    ??四、標簽 ......

    uj5u.com 2022-12-18 07:17:06 more