web前端開發筆記整理(六)

JavaScript對象克隆

淺拷貝

淺拷貝引用值是要相互影響的,因爲它是棧內存之間的賦值,賦值的是地址,一個更改,其他的都要更改。

var obj = {
        name :'abc',
        age  : 123,
        sex : 'female',
        card : ['visa','master']//存在一個引用值
    }
    var obj1 = {}
    function clone(origin,target) {
        var target = target || {};//防止沒有提前新建一個空對象
        for(var prop in origin){
            target[prop] = origin[prop];
        }
    }
    clone(obj,obj1);

深度拷貝

深拷貝就是無論是原始值還是引用值,修改後彼此相互不影響。
遍歷對象 for(var prop in obj)(for in也可以遍歷數組(數組也是特殊類型的對象))
1,判斷是不是原始值 typeof() object—>引用值
2,判斷是數組還是對象 constructor,instanceof,toString
3,建立相應的數組或者對象
4,遞歸

// JavaScript Document
var obj = {
        name :'abc',
        age  : 123,
        sex : 'female',
        card : ['visa','master']//存在一個引用值
    }
    var obj1 = {}

function deepClone(origin, target){
    var target = target || {},
        toStr = Object.prototype.toString,
        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] = {};
                //    }   
                //上面的ifelse條件判斷可以用下面的三目運算符代替: 
                target[prop] = toStr.call(origin[prop]) == arrStr ? [] : {};
                deepClone(origin[prop],target[prop]);  
                
                }else{
                    target[prop] = origin[prop];
                }
            }
        }
        return target;
}
deepClone(obj,obj1);

在這裏插入圖片描述
更改引用值之間相互不影響
在這裏插入圖片描述

數組

數組的兩種創建方式

  • var arr = [];//字面量(內部還是new Array()的方式)

  • var arr = new Array();

改變原數組方法

  • push()

功能:在數組的最後一位新增一個或多個數據,並且返回新數組的長度,會改變原來的數組
注意:push()方法返回的是數據是新數組的長度,它增加的數據可以是一個也可以是多個,可以理解爲增加一連串的數據

在這裏插入圖片描述在這裏插入圖片描述

模擬系統調用數組的push方法:
Array.prototype.push = function(){
    for(var i = 0; i <arguments.length; i++){
        this[this.length] = arguments[i];
    }
    return this.length;
}
  • pop()

功能:刪除數組的最後一位,並且返回刪除的數據,會改變原來的數組
注意:帶了參數也沒得用,還是刪除最後一個
在這裏插入圖片描述

  • shift()

功能:刪除數組的第一位數據,並且返回新數組的長度,會改變原來的數組
在這裏插入圖片描述
帶不帶參數都是一樣的,只剪切數組的第一個元素

在這裏插入圖片描述

  • unshift

在數組的第一位添加元素。返回的是數組的長度
在這裏插入圖片描述

  • sort
    數組直接調用sort()方法,它是 按照ASCII排序的。

ASCII比較大小的時候,是比較兩個數中的第一個字符。

  • 常見ASCII碼的大小規則,0-9<A-Z<a-z:
  • 數字比字母要小。如 “7”<“F”
  • 數字0比數字9要小,並按0到9順序遞增。如 “3”<“8”
  • 字母A比字母Z要小,並按A到Z順序遞增。如“A”<“Z”
  • 同個字母的大寫字母比小寫字母要小32。如“A”<“a”

記住幾個常見字母的ASCII碼大小: “A”爲65;“a”爲97;“0”爲48;
在這裏插入圖片描述

讓數組按照大小排序就要實現sort高階函數的使用
1,必須寫兩個形參
2,看返回值
1)當返回值爲負數時,那麼前面的是放在前面
2)當返回值爲正數時,那麼後面的是放在前面
3)爲0,不動

var arr= [1,3,5,4,10];
arr.sort(function (a,b) {
   if(a > b){
       return 1;
   }else{
       return -1;
   }
});
console.log(arr);//[1,3,4,5,10]

上面高階sort函數的實現可以簡化爲下面這種形式:

arr.sort(function (a,b) {
  return a-b;//升序
//  return b-a;//降序
});

它是這樣的執行過程,數組裏面的數首先傳a= 1,b = 3,1和3比,然後1,4。1,5。1,10 。3,4。3,5 。3,10 。4,5 。4,10 。5,10 。

這樣多次調用裏面的函數進行比較(就想冒泡排序一樣)

因爲 if(a > b){return 1;}就可以爲 if(a - b > 0){return 1;}—>return a - b

因爲這個時候a> b,只要返回整數就可以了

然後再else裏面就是a<b返回負數,那麼return a-b肯定是負數。所有它們都返回的是a-b,直接一下子就返回a - b

給一個有序的數組排序,讓它每一次執行都是亂序

var arr = [1,2,3,4,5,6,7];
arr.sort(function () {
   return Math.random() - 0.5;
});


console.log(arr);
  • 發現每執行一次,arr數組裏面的順序都不一樣。

  • 因爲 Math.random()返回的結果是(0,1),這樣減去0.5,那麼它有爲正的概率和爲負的概率是一半一半。

  • 根據sort函數的原理,如果返回的是正數,那麼後面的和前面的調個位置,如果返回的是負數或者0,那麼前面的還是在前面

將數組裏面的按字節長度排序

var arr = ['ac','nsfauigf','網絡','osy題詞','wdfewfef','addasd'];
function retBytes(str) {
    var num = str.length;
    for(var i = 0; i <str.length; i++){
        if(str.charCodeAt(i) > 255){
            num++;
        }
    }
    return num;
}
arr.sort(function(a,b) {
    return retBytes(a) - retBytes(b);
})
  • reverse

數組反轉
在這裏插入圖片描述

  • splice

splice ( 從第幾位開始截取 , 截取多少位 , 在截取點處添加什麼)
在這裏插入圖片描述

在這裏插入圖片描述

負數的實現原理是這樣的:pos += pos > 0 ? 0 : this.length;也就是倒數的第幾位
首先判斷,如果是負數的話那就是負數加上長度就等於正數的第幾位(從0開始)
在這裏插入圖片描述

不改變原數組方法

  • concat
var arr = [1,2,3]
var arr1 = [4,5,6]
var arr3 = arr.concat(arr1);//arr3 : [ 1, 2, 3, 4, 5, 6 ]

例題:
把這一串字符串鏈接起來,不用+號的方式(因爲字符串是原始值,存在棧內存裏面的,這樣來回在棧內取元素很浪費時間。 )。

var str1 = "nsd";
var str2 = "sdsfd";
var str3 = "fadf";
var arr = [str1,str3];//數組是散列結構
console.log(arr.join(""));//nsdfadf
//console.log(arr.join());// nsd,fadf

join()裏面爲空就是用逗號連起來。

數組的方法join 和 字符串的方法split是互逆的

var arr= [1,2,3,4,5]; 
var str = arr.join("-"); // "1-2-3-4-5"
var shuzu =str.split("-");//[ "1", "2", "3", "4", "5" ]
  • toString
var arr = [1,2,3,4]
console.log(arr.toString());//1,2,3,4
  • slice

返回值是截取的值,不改變原數組。

  • slice兩個參數(從該位爲開始截取,截取到該位)

  • slice一個參數(從該位開始截取到後面所有都截取)

  • slice沒有參數(整個截取)
    在這裏插入圖片描述
    在這裏插入圖片描述

類數組

  • 可以利用屬性名模擬數組的特性
  • 可以動態的增加length屬性
  • 如果強行讓類數組調用push方法,則會根據length屬性值的位置進行屬性值的擴充。
    類數組舉例

1,arguments
2,一個對象:屬性要爲索引(數字)屬性,必須有length屬性,最好加上push

類數組裏面最關鍵的是length屬性,類數組中push實現的原理

Array.prototype.push = function (target) { 
    obj[obj.length] = target;
    obj.length++;
}
var obj = {
    "2" : "a",
    "3" : "b",
    "length" : 2,
    "push" : Array.prototype.push
}
obj.push('c');
obj.push('d');
console.log(obj);
//Object { 2: "c", 3: "d", length: 4, push: push() }
var obj = {
    "1" : "a",
    "2" : "c",
    "3" : "d",
    "length" : 3,
    "push" : Array.prototype.push
}
obj.push('b');
console.log(obj);
//Object { 1: "a", 2: "c", 3: "b", length: 4, push: push() }
var obj = {
    "0" : 'a',
    "1" : 'b',
    "2" : 'c',
    name :"abc",
    age  : 123,
    length : 3,
    push : Array.prototype.push,
    splice :Array.prototype.splice
}

類數組的好處就是把數組和對象的好處拼到一起,
但是並不是所有的數組方法都能用,除非你自己添加

封裝typeof方法

1,分兩類,原始值和引用值
2.區分引用值

function type (target){  
    var ret = typeof(target);
    var template = {
        "[object Array]" : "array",
        "[object Object]" : "object",
        "[object Number]" : "number-object",
        "[object String]" : "string-object",
        "[object Boolean]" : "boolean-object"
    }
    if(target === null){
        return "null";
    }else if(ret == 'object'){//引用值:數組,對象,包裝類
     var str = Object.prototype.toString.call(target);
        return template[str];//屬性值
    }else{
        return ret;//原始值:直接用typeof來區分
    }
}

數組去重(要求在原型鏈上編程)

var arr = [1,1,1,1,2,2,2,2,2];
//利用對象的一個屬性只能對應一個值的特性來去重
//var obj = {
//    "1" : 'abc',
//    "2" : 'abc,
//}
"1"-->undefined
"1"-->"abc"
"2"-->undefined
"2"-->"abc"

//新建一個對象,遍歷數組裏面的每一個值拿來當做對象的一個屬性,如果該屬性已經存在了值,那就跳過,繼續找下一個值。
//看它是不是爲對象在對象裏面已經有了值,如果沒有值,那就把數組裏面的這個值作爲該對象的一個新的屬性。
//最後輸出對象的所有屬性就是去掉數組裏面重復的值。

Array.prototype.unique = function () {
    var temp = {};					//新建一個空對象
    var arr = []; 					//新建一個空數組,用來返回 去重後的結果 
    var len = this.length;
    for(var i = 0; i < len; i++){
        if (!temp[this[i]] ) { 		//this[i]表示arr[i]表示數組裏面的每一個值
     							   //temp[this[i]]表示對象裏面的這個屬性(數組裏面的值)的值是不是undefined,如果是undefined,就說明這要添加到該對象裏面爲一個新的屬性。
     							   //所以這個地方就是!temp[this[i]],表述如果它是!undefined == true就要給它賦值,然後push到去重數組裏面去。
            temp[this[i]] = 'abc';
            arr.push(this[i]);
        }
    }
    return arr;
}

ES5嚴格模式

Javascript 的保留關鍵字不可以用作變量、標籤或者函數名。有些保留關鍵字是作爲 Javascript 以後擴展使用。ES5較ES3新添加了幾個保留關鍵字:

1)class:類,ES6引入
2)const:常量,ES6引入
3)enum:枚舉類型
4)extends:類繼承,ES6引入
5)import:模塊導入,ES6引入
6)export:模塊導出,ES6引入
7)super:調用父類的構造函數,ES6引入
瀏覽器兼容性

1)ES3,可以認爲所有瀏覽器都支持;
2)ES5,現代瀏覽器都支持(>=IE9), IE9不支持嚴格模式。

在try裏面的發生錯誤,不會執行錯誤後的try裏面的代碼

  • try 測試代碼塊的錯誤。
  • catch 語句處理錯誤。
  • throw 創建並跑出錯誤。
try
   {
   //在這裏運行代碼
     拋出錯誤
   }
 catch(err)
   {
   //在這裏處理錯誤
   }

請輸出一個 5 到 10 之間的數字:

<input id="demo" type="text">
<button type="button" onclick="myFunction()">測試輸入</button>
<p id="mess"></p>

</body>
</html>
<script type="text/javascript">
    function myFunction(){
    try{ 
        var x=document.getElementById("demo").value;   取元素的值
        
        if(x=="")    throw "值爲空";       根據獲取的值,拋出錯誤
        if(isNaN(x)) throw "不是數字";
        if(x>10)     throw "太大";
        if(x<5)      throw "太小";
    }
    catch(err){
        var y=document.getElementById("mess");     抓住上面throw拋出的錯誤,給p標籤顯示
        y.innerHTML="錯誤:" + err + "。";
    }
}
</script>

Error.name的六種值對應的信息

  • EvalError : eval()的使用與定義不一致

  • RangeError : 數組越界

  • ReferenceError : 非法或不能識別的引用數值(一般沒有定義就使用就會報ReferenceError)

  • SyntaxError :發生語法解析錯誤

  • TypeError : 操作數類型錯誤

  • URIError : URI處理函數使用不當

es5.0嚴格模式

啓動es5.0的嚴格模式用"use strict" ,放在邏輯的最頂端(全局嚴格模式),或者放在局部的最頂端讓它部分啓用es5.0的嚴格模式(局部函數內的嚴格模式)。

這個時候和es3.0產生衝突的部分全部使用es5.0的嚴格模式

"use strict"就是一行字符串。不會對不兼容嚴格模式的瀏覽器產生影響

不支持with,arguments.callee,function.caller

 var obj={
     name:"obj"
 }
 var name='window';
 function test(){
     var name="scope";
     with(obj){
         console.log(name);
    }
 }
 test()

with它會改變作用域鏈,with(obj)裏面跟的obj會被放在作用域的最頂端,那麼首先查找作用域鏈的時候就會找obj裏面的。因爲with的功能太強大,消耗大量的資源。所以在嚴格模式裏面不準用

變量賦值前必須聲明。
  var a = b = 3;//會報錯,b報錯

局部this必須被賦值(Person.call(null/undefined)賦值什麼就是什麼) ,就是說預編譯this不再指向window,它爲undefined,在全局範圍裏面this依舊是指向window。

es5拒絕重複的屬性 和參數
eval是魔鬼
eval 能該表作用域

數組去重

第一種方法用ES6裏面的Set特性來去重

var arr = [4,7,9,4,7,8,9,4];
        var set = new Set();
        for(var i = 0; i< arr.length; i++){
            set.add(arr[i]);
        }
        console.log(set);

第二種方法用一個新的數組裏面indexOf屬型的性質來去重
(indexOf返回的就是字符出現在字符串的位置,或者判斷字符串出現在數組的位置,返回數組的下標)

   var newArr=[];
    for(var i = 0; i < arr.length; i++){
        if(newArr.indexOf(arr[i]) == -1){
            newArr.push(arr[i]);
        }
    }
    console.log(newArr);

第三種方法就一句就可以實現去重

  console.log(Array.from(new Set(arr)));

尋找落單

第一種方法:用ES6裏面的Set去重留下落單的那個。

var arr = [1,2,3,4,5,1,2,3,4];
        var set = new Set();
        for(var i = 0; i <arr.length; i++){
            if(set.has(arr[i])){
                set.delete(arr[i]);
            }else{
                set.add(arr[i]);
            }
        }
        console.log(set);//結構是一個數組:   Set(1) {5}
        console.log(...set);//5  用展開運算符把數組展開

第二種方法:根據對象的屬性是不允許有重複的這一特性。

var arr = [1,2,3,4,5,1,2,3,4];
        var obj = {};
        for(var i  = 0; i < arr.length; i++){
            if(obj[arr[i]]){
                delete obj[arr[i]];
            }else{
                obj[arr[i]] = true;
            }
        }
        console.log(Object.keys(obj)[0]);//通過這種方法拿到對象的key

第三種方法用到了異或^
首先你要知道0和任何數異或都等於任何數,然後任何數和自己異或都爲0,
因爲相同爲0,不同爲1,它也存在交換律和結合律。
所以用它在找那個落單的數,是一定可以找到的。

var arr = [1,2,3,4,5,1,2,3,4];
        var result = 0
        for(var i  = 0; i < arr.length; i++){
            result ^=arr[i];
        }
        console.log(result);

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章