JavaScript知識點

1、JavaScript特色javascript

  1. 解釋性語言——不須要編譯代碼,能夠跨平臺,像php、js、jsp都是解釋性語言。
  2. 單線程——js是單線程的語言,同時只能執行一件事情
  3. ECMA標準——爲了統一js的規則,推出了ECMA標準,所以js也稱爲ECMAScript。

2、JavaScript三大部分:(ECMAScript、DOM、BOM)

  1. ECMAScript是符合ECMA標準的基本javascript。
  2. DOM是Document Object Model文檔對象模型,能夠操做頁面的代碼,能夠操做html和css部分。DOM是很是很是重要的部分。
  3. BOM是Browser Object Model瀏覽器對象模型,操做瀏覽器shell的。由於每個瀏覽器廠家的不一樣,致使咱們在每個瀏覽器操做BOM都不同。

3、JavaScript的基本語法

  1. 變量聲明php

  • Js是一種弱數據類型的語言,任何類型的變量都用關鍵字Var來聲明。
1 var arr = [1,2,3];
2 var num = 123;
3 var steing = "abc";
  • 賦值能夠在聲明的的同時賦值,也能夠在後面賦值。
1 var num = 123;
2 var num;
3 num = 123;
  • 這兩種方法是同樣的。
  • 同時有一種單一Var模式。
1 var num1 = 123,
2     num2 = 234,
3     num3 = 456;
  • 變量名上下對齊,這樣結構更清晰,也能節省不少代碼。

2.變量命名規則css

  • 以英文字母開頭或者_和$符開頭。
  • 變量名能夠包含數字。
  • 不可使用系統自帶的關鍵字,保留字。

3.數據類型(值類型)html

  • 不可改變的原始值。
  • 主要有 Number String Boolean undefined null 堆數據。
  • 引用值 數組Array 對象Object 函數function 棧數據。

4、JavaScript語句的基本規則

  1. 語句後面要用英文「 ;」結束。
  2. js語法錯誤會引起後續代碼的終止,但不會影響其餘的js代碼塊,這裏僅限於邏輯錯誤和低級語法錯誤會致使代碼所有執行不了。
  3. 書寫規範(不一樣公司有不一樣要求)。

5、JavaScript運算符

  1. 「 + 」數學上相加的功能和字符串拼接「- * / % 」數學運算。
  2. 相同的還有「++ == -- += -= > < ...」等等。
  3. 邏輯運算符 && || !
  • && 的做用是結果是true的時候纔會繼續執行,第一個就錯了第二個不會執行,若是都是true的話返回最後一個。
  • || 的做用是結果只要有一個表達式是true的,後面的就不走了,而且返回的結果是這個正確的表達式的結果,全是false表達式返回的結果就是false。
  • && 能夠當作一種短路語言使用;|| 能夠當作賦初值的使用。

4.默認爲false的值java

  • unedfined; null; " "; NaN; 0; false 。

6、類型轉換

(一)顯示類型轉換
  1. 用 typeof 能夠檢測數據的類型。
1 console.log(typeof(123)); // Number
  • typeof 返回的結果有六種:number string boolear undefined object function 。
  • 數組和 null 都屬於object。
  • NaN 屬於number ,雖然是非數,但也屬於數字。
  • typeof 返回結果是字符串。

2.Number(mix)[混合]es6

  • 這個方法是能夠把其餘類型的數據轉換成數字類型的數據。

3.parseInt(string,radix)[基數]shell

  • 這個方法是將字符串轉換成整型類型數字的。其中第二個參數radix基底是能夠選擇的參數。
  • 當radix爲空的時候,這個函數的做用僅僅是將字符串轉換成number類型。
  • 當參數string裏面既包括數字字符串又包括其餘字符串的時候,它會將看到其餘字符串就中止了,不會繼續轉換後面的數字型字符串了。
1 parseInt('123abc123') // 123;
2 parseInt('abc123')    // NaN;
3 parseInt('123')       // 123;
4 parseInt('true')      // NaN;
  • 當radix不爲空的時候這個函數能夠用做進制轉換,把第一個參數的數字當成幾進制的數字轉換成十進制。
  • radix參考範圍是2--36,
1 var demo = 10;
2 parseInt(demo,16) //16

4.parseFloat(radix)數組

  • 這個方法和parseInt相似,是將字符串轉換成浮點類型的數字,碰到第一個非數字類型中止。
  • 只能識別第一個小數點及後面的數字,第二個小數點不能識別。
1 parseFloat('123.2.3')  // 123.2
2 parseFloat('132.2abc') // 123.2
3 parseFloat('123.abc1') // 123

5.toString(radix)瀏覽器

  • 這個方法和前面的不一樣,它是對象上的方法,任何數據類型均可以使用,轉換成字符串類型,涉及到包裝類。
  • 一樣是radix基地可選參數,爲空僅僅將數據轉換成字符串。
1 var demo = 123;
2 typeof demo.toString(); // string123;
3 typeof true.toString(); // stringtrue;
  • 當寫了radix時表明要將這個數字轉換成幾進制的數字型字符串。
1 var dome = 10;
2 demo.toString(16) // A
  • undefined和null沒有toString方法

6.String(mix)閉包

  • 和Number相似把任何類型轉換成字符串

7.Boolean(mix)

  • 和Number相似把任何類型轉換爲Boolean
(二)隱式類型轉換

1.isNaN()

  • 這個方法能夠檢測是否是非數類型,調用的Number方法。

2.算數運算符

  • ++就是將現有數據調用Number以後,自身加一。
  • + - * / 執行以前都會先進行類型轉換,換成數字在運算。

3.邏輯運算符

  • && || ! 都會調用Boolean轉換成布爾值看看結果是ture仍是false,返回結果仍是自己表達式的結果。
  • // !abc; // false

4.不發生類型轉換的比較運算符

  • ===嚴格等於 !==嚴格不等於

7、預編譯【precompile】

函數聲明提高:函數聲明提高是一種總體提高,他、它會把函數聲明和函數體一塊兒提到前面。

變量聲明提高:變量聲明提高是一種局部提高,它僅僅將變量的聲明提早了,可是並無將賦值一塊兒提高。

 1.js運行三部曲

  • 語法分析
  • 預編譯
  • 解析執行

2.預編譯前奏

  • imply global
  • 暗示全局變量,若是任何變量未經聲明就賦值使用,此變量歸window全部,而且成爲window對象的一個屬性。
  • 一切聲明的全局變量,都是window屬性。
  • 未經聲明的全局變量能夠用delete操做來刪除。
  • 函數在執行的前一刻一個執行上下文,Activeaction Object對象。
  • 這個對象是空的,可是裏面有着一些看不見的隱式屬性:this:window屬性和arguments[];屬性。

3.預編譯四步

  • 建立AO對象
  • 尋找形參和變量聲明並當作屬性名添加到AO對象中,值爲undefined。//函數聲明不叫變量。
  • 將實參形參相統一
  • 在函數體裏尋找函數聲明,將函數名當作屬性名,值爲這個函數的函數體。
複製代碼
 1  function test (a,b) {
 2      console.log(a)
 3      function a () {}
 4      a = 222;
 5      console.log(a)
 6      function b () {};
 7      console.log(b)
 8      var b = 111;
 9      var a;
10  } 
11  test(1);
複製代碼
  • var b = function () {} 這種不叫函數聲明,這個函數是給b賦值的,b變量是聲明。
  • 在第四步尋找函數聲明並不會把賦值成function(){},執行到這一行的時候纔會賦值成這個函數。

10、函數與做用域與閉包

(一)函數部分

1.函數聲明有3種方式

1 var demo = function () {}; 函數表達式
2 function demo () {}; 函數聲明
3 var demo = function xxx () {};命名函數表達式   //沒用
  • 每個函數裏面都有一個類數組屬性arguments,這個屬性裏面存的就是實參。
  • 每個函數有一個length屬性,這個屬性存的是形參的數量。
  • 每個函數都會有一個return,若是不寫的話函數會自動加一個return。
  • return的功能有兩個:返回這個函數的執行結果、終止函數的執行。
複製代碼
1 function test(a,b) {
2     console.log(a + b);
3     return;
4     console.log('hello');
5 }
6 test(1,2);  //  打印結果3   不會打印hello
複製代碼
(二)做用域
  • 定義:變量(變量做用域又稱爲上下文)和函數生效(能被訪問)的區域。
  • JavaScript的函數是能夠產生做用域的。
  • es5中的做用域只有全局做用域函數做用域兩種,es6新添加的塊級做用域。
複製代碼
1 var demo = 123;  // 全局變量
2 function test () {
3   var demo = 234; // 局部變量
4   console.log(demo);
5   var demo1 = 'hello';
6   }
7 test(demo);  // 打印234    就近打印局部變量,沒有局部變量打印全局變量
8 console.log(demo1); // 報錯 咱們的全局做用域沒法訪問局部做用域
複製代碼
  • 函數做用域就好像一個屋子,裏面的能夠拿外面的東西,外面的不能拿裏面的東西。
  • 在函數做用域裏聲明變量沒有用var的話,那麼就生成了一個全局變量。
  • 兩個不一樣的做用域(除了全局做用域)是不能互訪問的。
(三)做用域鏈(scope chain)
  • 既然函數存在做用域,函數有能夠嵌套,那麼做用域就會產生嵌套關係,這個時候就產生做用域鏈。
  • 當代碼在一個環境中執行時,會建立變量的做用域鏈來保證對執行環境有權訪問的變量和函數的有序訪問。
  • 做用域鏈第一個對象始終是當前執行代碼所在環境的變量對象。
複製代碼
1  function demo () {
2     var dome_a = 1;
3     function test () {
4         var demo_a = 2;
5         console.log(demo_a);
6     }
7     test();
8  }
9  demo();
複製代碼
  • 本着對執行環境的有權和有序訪問,每一個函數的自身做用域總在做用域鏈的最頂層,下一層就是這個函數的父級函數做用域,直到全局做用域。
  • 所以test執行的時候打印的demo_a是自己做用域中的是‘2’而不是‘1’,若是自身做用域沒有demo_a的話系統就會沿着做用域鏈向下找demo_a。
(四)閉包【closure】

1.什麼是閉包

  • 閉包就是可以讀取其它函數內部變量的函數。
  • 不一樣的做用有之間不能互相訪問,可是若是在一個函數內部再定義一個函數與外部的變量有所關聯,那麼就能夠返回這個函數來訪問外部函數裏面的變量,因此在本質上閉包就是將函數內部與函數外部鏈接起來的橋樑。
複製代碼
 1  function a (){
 2     var dome1 = 123;
 3     add = function(){
 4         demo1 ++;
 5     }
 6     return function(){
 7         console.log(demo1);
 8     };
 9  }
10 var demo = a ();
11 demo();    // 123
12 add();   
13 demo();    // 124
複製代碼
  • 當函數執行完函數的執行上下文就會被銷燬,天然就沒法訪問裏面的變量了,可是咱們這個函數返回了一個依賴於這個函數的新函數,也就是說這個沒有被銷燬的新函數的做用域鏈中存在着本來函數做用域的引用,就致使本來函數的上下文不會被銷燬,返回的新函數是本來函數的閉包函數。

2.使用閉包的注意點

  • 閉包會使函數的變量都保存在內存中,內存消耗很大,不能濫用閉包,不然會形成網頁的性能問題,IE會形成內存泄漏。解決的方法就是退出函數時,將不使用的局部變量所有刪除。
  • 閉包會在父函數外部改變父函數內部的值,若是把閉包當對象使用,那麼就把閉包當作它的公用方法,把內部變量當作它的稀有屬性。(不要隨便改變函數內部變量的值)
複製代碼
 1 var name = 'global';
 2 var obj = {
 3       name:'obj',
 4       getName:function() {
 5             return function () {
 6                  console.log(this.name);
 8                 }
10            }
11     }  
12 obj.getName() ();      
複製代碼
  • 累加器的例子:
複製代碼
 1  function a () {
 2      var num = 1;
 3      function addNum () {
 4          num ++;
 5          console.log(num);
 6      }
 7      return addNum;
 8  }
 9  var demo = a ();
10  demo();
11  demo();
12  var demo1 = a();
13  demo1();
14  demo1();
複製代碼
(五)當即執行函數
  • 當即執行函數是解閉包的一個重要方法,可是注意閉包是沒有辦法解除的,只能經過一個新的閉包來消除上一個閉包的影響。
  • 當即執行函數不須要被定義,直接執行,執行完釋放,常常做用做初始化。
  • 函數聲明不能被執行,可是函數表達式能夠
複製代碼
 1  (function (){}())
 2  function returnB() {
 3      var arr = [];
 4      for(i = 0; i < 10; i ++){
 5          arr[i] = (function(){
 6              console.log(i);
 7          }())
 8      }
 9      return arr;
10  }
11  var save = returnB();
12  console.log(save);
13  for(j = 0; j < 10; j ++){
14      save[j];
15  }
複製代碼

11、對象、構造函數與包裝類

1.對象的建立方式有三點

  • 對象字面量。
1 var obj ={};
  • 這樣的方式是最簡單最經常使用的方法。
  • 對象裏面有屬性,屬性之間用逗號相隔,每條屬性都有屬性名和值,屬性名和屬性值用分號相隔。

2.構造函數【constructor】

  • 構造函數也分爲兩種,系統自帶的構造函數和自定義的構造函數。
  • 建立對象的構造函數Object()
1 var object = new object();
  • 經過這條語句就建立了一個空對象,它的做用和 var obj = {}; 的做用同樣。
  • 系統自帶的構造函數還有Number();String();Boolean();Array() 。

3.自定義構造函數

  • 自定義的構造函數是最多見的一種構造函數。
1  var function Person () {};
2  var operson = new Person ();
3  typeof operson  // object
  • 用new操做符創造出來的對象,儘管使用的是一個構造函數,可是之間沒有聯繫。
複製代碼
1  function Person (name,age) {
2      this.name = name;
3      this.age = age;
4  }
5  var person = new Person('zhangsan',18);
6  console.log(person.name);
複製代碼
  • 建立對象的時候只有new纔會有this。
  • 重點:爲何能夠用new操做符建立出相互獨立的對象呢?
  • 用new操做符的時候,這個new在構造函數裏面隱式的建立了一個this對象,而且最後返回了這個this對象。
1 function Person (name) {
2         var this = {};
3         this.name = name;
4             return this;
5   }
  • 若是在構造函數首行手動建立一個對象,好比that對象,而後返回that,那麼裏面的this就沒有了,屬性值就用that了。
複製代碼
1  function Person (name) {
2      var that = {
3          name: 'lisi'
4      };
5      that.name = name;
6      return that;
7  }
8  var person = new Person ('demo');
9  console.log(person.name)
複製代碼
  • 若是最後返回的是對象,那麼this就失效,可是若是顯示返回的是原始值那麼this仍是有效的。

4.屬性的增刪改查

  • 增:能夠經過對象名+點屬性名的方法來給對象添加新的屬性而且賦值。
1 var obj = {};
2 obj.name = 'xiaoming'
  • 改:修改的操做增長是同樣的,只要調用相同的屬性名而後賦一個新值就能夠了。
1  var obj = {
2    name:'demo';
3  }
4  obj.name = 'tan';
  • 查:查看屬性的功能console.log(xxx)。
  • 刪:刪除屬性須要藉助delete操做符。
複製代碼
1  var obj = {
2      name = 'scerlett'
3  }
4  obj.name;  // scerlett
5  delete obj.name;
6  obj.name;  // undefined
複製代碼
  • 包裝類

12、原型與原型鏈

(一)原型:prototype

1.原型的定義:原型是function對象的一個屬性,它定義了構造函數製造出來的對象的公有祖先,經過該構造函數產生的對象,能夠繼承原型的屬性和方法,原型也是對象。

1 function Person () {}
  • 定義一個構造函數,Person.prototype這個屬性就是這個構造函數的原理,這個屬性天生就有的,而且這個屬性的值也是一個對象。
  • 能夠在person.prototype上面添加屬性和方法,每一構造出來的對象均可以繼承這些屬性和方法。
  • 雖然每個對象都是獨立的,可是它們都有共同的祖先,當訪問這個對象屬性的時候,若是它沒有這個屬性,就會向上查找,找到它原型,而後在原型上訪問這個屬性。

2.利用原型特色概念,能夠提取公有屬性

  • 能夠把每個對象都有的公有屬性不寫在構造函數裏面,而是提取到原型上,這樣當構造函數構造大量的對象的時候就不須要走屢次構造裏面的賦值語句了,而只需走一遍,每一個對象調用屬性的時候直接上原型上查找就能夠了。

3.對象如何查看原型

  • 用構造函數構造對象的時候,就會隱式建立一個this對象,這個this對象裏面有一個默認的屬性叫作proto屬性,這個屬性的值就是指向對象的原型。
  • 當查找的屬性是自身沒有的屬性的時候,就會查找proto這個屬性,而後這個屬性指向原型,因此就到原型上查找屬性了。
  • 注意:prototype是函數的屬性,proto是對象的屬性。

4.如何查看構造自身的構造函數

  • 在prototype裏面,有一個隱式的屬性叫作constructor,這個屬性記錄的就是對象的構造器,裏面存的就是構造函數。
1 console.log(person.constructor); //person();
(二)原型鏈

1.有了原型,原型仍是一個對象,那麼這個名爲原型的對象天然還有本身的原型,這樣的原型上還有原型的結構就成了原型鏈。

複製代碼
 1  Gra.prototype.firsName = 'scarlett'
 2  function Gra () {
 3      this.name = 'grandfather';
 4      this.sex = 'male';
 5  }
 6  var grandfoo = new Gra();
 7  garndfoo.word = 'hello'
 8  Foo.prototype = grandfoo;
 9  function Foo () {
10      this.age = '18';
11      this.money = '100';
12  }
13  var father = new Foo();
14  function Son () {
15      this.name = 'son';
16  }
17  Son.prototype = father;
18  var son = new Son();
複製代碼
  • Foo創造出來的每個對象都繼承來自grandfoo對象,son的每一對象都繼承來自father這個由Foo創造出來的對象,這樣的son就能夠繼承上面Foo和Gra的全部屬性。
  • 這種鏈式的查詢結構就叫作原型,最終的盡頭是Object.prototype這個對象。
  • 若是沒有規定原型的對象,它的原型就是Object.prototype。

2.可是並非全部的對象都有原型,好比使用Object.create方法。

  • Object.create()方法須要寫一個參數,這個參數就是對象的原型,若是要構造一個var obj = {};同樣的對象,就須要寫:
1 var obj = Object.create(Object.prototype);
  • 也能夠寫一個自定義的屬性,讓它成爲原型。

3.原型鏈上的增刪改查

1 Person.prototype.arr[1,2,3];
2 var person1 = new Person();
3 var person2 = new Person();
4 person1.arr.push(4);
5 console.log(person2);//1 2 3 4 
  • 刪:刪除屬性須要藉助delete操做符,對象不能刪除原型上的屬性。

 十3、繼承、this

1.this的一些問題:

函數內部的this默認指向window,可使用call / apply來改變this的指向,區別:後面傳參形式不一樣。

1 function person () {
2   this.name = 'scarlett';
3   console.log(this);
4   }
5   person();

  如今this指向window,name屬性天然就是window上的全局屬性

var obj = {};

person。call(object)//Object.{name:'scarlett'}

  若是這個函數還有參數的話,只要把實參的值寫在call後面而且用逗號隔開

複製代碼
 function person(name,age){
     this.name = name;
     this.age = age;
 }
 var obj = {};
 person.call(obj,'scarlett',18);
 console.log(obj.name);
複製代碼

  apply和call基本沒什麼區別,惟一的區別就是call後面的參數是一個一個傳的,而apply後面的參數是放在數組裏

person.apply(obj['scarlett',18]);

2.繼承【inherit】

  聖盃模式

複製代碼
function inherit(Target, Origin) {
    function F() {};
    F.prototype = Origin.prototype;
    Target.prototype = new F();
    Target.prototype.constuctor = Target;//讓constuctor指向本身的
    Target.prototype.uber = Origin.prototype; //超類,知道本身繼承的是誰
複製代碼

  yahu封裝方法:

複製代碼
 1 // var inherit = (function (){
 2 //     var F = function () {};
 3 //     return function (Target, Origin){
 4 //         F.prototype = Origin.prototype;
 5 //         Target.prototype = new F();
 6 //         Target.prototype.constuctor = Target;
 7 //         Target.prototype.uber = Origin.prototype;
 8 //     }
 9 // }());
10 // 
11 //         for (var i = 0; i < 5; i ++) {
12 //             var btn = document.createElement('button');
13 //             btn.appendChild(document.createTextNode('Button' + i));
14 //             btn.addEventListener('click', function(){console.log(i); });
15 //             document.body.appendChild(btn);
16 //         }
複製代碼

  對象的枚舉與this

1.對象的枚舉

  查看對象的屬性能夠用obj.name查看,也能夠用obj['name']類數組方式查看,但事實上是數組模仿了對象的查看方式

2.for-in操做符

  要枚舉一個數組的全部屬性只需用一個for循環從頭至尾遍歷一遍就能夠了。

  可是對象並不能用for循環來遍歷屬性,全部就要用到for-in操做了

複製代碼
1 // var obj = {
2 //     name: 'scarlett',
3 //     age: 18,
4 //     sex: 'female'
5 // }
6 // for(var prop in obj){
7 //     console.log(prop + ':' + obj[prop]);
8 // }
複製代碼
  • for-in循環會按照屬性的順序取出屬性名而後賦給prop,全部打印prop都是屬性名,obj【prop】則是性對應的屬性的值
  • 注意:這裏不能寫成obj.prop方式,由於在系統底層會轉化成obj【‘prop’】的形式,可是並無prop屬性,它只是一個變量,因此會打印  undefined,這裏必須使用obj['prop']。
  • 在非嚴格模式中,for-in循環都會把原型裏面的一些屬性一塊兒打印出來,但es5的嚴格模式不會。

2.三種操做符

  hasOwnProperty這個操做符的做用是查看當前這個屬性是否是對象自身的屬性,在原型鏈上的屬性會被過濾掉,自身的ture

複製代碼
// function Person() {
//     this.name = 'scarlett'
// }
// Person.prototype = {
//     age:18
// }
// var oPerson = new Person();
// for (var prop in oPerson) {
//     if (oPerson.hasOwnProperty(prop)){
//         console.log(oPerson[prop]);
//     }
// }
複製代碼

  這樣for-in循環就只會打印自身的屬性,而不是打印原型上的屬性

  in操做符:這個操做符的做用是查看一個屬性是否是在這個對象或者它原型裏面。

1 // 'name' in oPerson;    //ture
2 // 'sex' in oPerson;   //False

  instanceof操做符:做用是查看前面對象是否是後面的構造函數構造出來的,和constructor很像

1 // oPerson intanceof object;    // ture
2 // {} instanceof oPerson;  // false

3.this

  • 預編譯過程當中this執行window
  • 全局做用域裏的this指向window
  • call / apply能夠改變this指向
  • obj.func()func()裏的this指向Obj
複製代碼
1 // var obj = {
2 //     height:190,
3 //     eat:function () {
4 //         this.height ++;  // eat在沒有執行以前,誰也不知道this指向誰
5 //     }
6 // }
7 // obj.eat(); // 誰調用this,this指向誰
8 // eat.call(obj); // eat裏面的this指向obj
複製代碼

  若是能理解下面的這段代碼的this指向問題,那麼就掌握的this的全部知識點了

複製代碼
 1 // var name = '222'
 2 // var a = {
 3 //     name:'111',
 4 //     say:function () {
 5 //         console.log(this.name);
 6 //     }
 7 // }
 8 // var fun = a.say;
 9 // fun();   // 此處其實就是把a.say這個函數體賦給fun這個函數,至關於在全局空間寫下了一個fun函數,此時this指向window,打印'222'
10 // a.say();  // 按照誰調用指向誰的說法,這裏打印'111'
11 // var b = {
12 //     name:'333',
13 //     say:function (fun) {
14 //         fun();
15 //     }
16 // }
17 // b.say(a.say); // 其實和在全局調用a.say的函數體方法差很少,打印'222'
18 // b.say = a.say;
19 // b.say(); // this指向B 因此打印'333'
複製代碼

十5、克隆與數組

1.argument.callee

  這個方法是指代函數自己,當在一些匿名函數或者當即執行函數裏面進行遞歸調用函數自己的時候,因爲沒有名字,就用這種方式調用;

  通常當須要經過計算機進行初始化的時候,寫一個當即執行函數,當這個當即執行函數還須要遞歸調用自身的時候,就用這種方式調用。

2.function.caller

複製代碼
// function test () {
//     console.log(test.caller);
// }
// function demo () {
//     test()
// }
// demo();
複製代碼

  這是函數自己自帶的一個屬性,能夠指出當前函數的ude運行環境的函數引用,就是這個函數在哪一個函數裏面執行的……

3.克隆【clone】

  克隆和繼承有一些區別,克隆是複製出來如出一轍的目標對象又分爲淺度克隆和深度克隆

複製代碼
// function clone (src,tar) {
//     var tar = tar || {};
//     for (var prop in src) {
//         if (src.hasOwnProperty(prop)){
//             tar[prop] = src[prop];
//         }
//     }
//     return tar;
// }
複製代碼

  當有一個屬性是引用值(數組、對象)時按照這種克隆模式,只是把這個引用值的指向賦給了新的目標對象,一旦改變了原對象或者目標對象的引用屬性另外一個也跟着變,這一點就是淺度克隆的缺點;

  深度克隆的原理很簡單,只要不克隆引用值的引用而是把引用值也當作一個原對象,把裏面的值一個個克隆島目標對象裏面,就解決了兩者相同指向的問題;

複製代碼
// function deepCopy (src,tar) {
//     var tar = tar || {};
//     for (var prop in src) {
//         if(typeof(src[prop] == 'object')){
//             tar[prop] = (src[prop].constructor === Array) ? [] : {};
//         }else{
//             tar[prop] = src[prop];
//         }
//     }
//     return tar;
// }
複製代碼

  這個時候目標對象和原對象的引用值就沒有關係了,都是獨立值能夠進行修改。

4.數組【array】

相關文章
相關標籤/搜索