程序猿都沒對象,JS竟然有對象?


  現在做項目基本是套用框架,不論是網上的前端還是后端框架,也會尋找一些封裝好的插件拿來即用,但還是希望拿來時最好自己過后再回過頭了解里面的原理,學習里面優秀的東西,不論代碼封裝性,還是小到命名。

  好吧,扯遠了,在這里要講的是大家前端用得多的JS,可能接觸最多的是Jquery,但原生的JS最好還是要了解的,至少能看懂別人的代碼,然后學習。

  平時用得多的無非是if for 邏輯處理字符串,截斷字符串,數組,然后是查找元素,對元素背景什么的屬性操作,這些都是些實用性上的東西,這里講一些更深入點的,如何理解Javascript對象。

  C#,Java都是面象對象的語言,但JavaScript本身不是面向對象的語言,而是基於對象的語言。 JavaScript中所有事物都是對象, 包括字符串、數組、日期、數字,甚至是函數(驗證方法是你可以在實例上 . 出屬性)。

  基於這點我們可以封裝自己的插件,這里就不講怎么制作插件了,想了解的可查詢我的如何制作插件的文章。

創建對象,平時用到的方法:

var emptyObject1 = {};           //創建空對象
var emptyObject2 = new Object(); //創建空對象
var person = {"name":"sdcyst",
          "age":18,           "sex":"male"};     //創建一個包含初始值的對象person alert(person.name);              //sdcyst alert(person["age"]);            //18

  注意上面如何訪問一個對象的屬性,通過"."操作符獲取對象的屬性,必須得知道屬性的名字.一般來說"[]"操作符獲取對象屬性的功能更強大一些,
  可以在[]中放入一些表達式來取屬性的值,比較有靈活性,如 name["name"+(i+1)];

  delete操作符可以刪除對象中的某個屬性,判斷某個屬性是否存在可以使用"in"操作符,需要注意的是對象中的屬性是沒有順序的。

var name = {"name1":"NAME1","name2":"NAME2","name3":"NAME3","name4":"NAME4"};
var namestring = ""; for(var props in name) {  //循環name對象中的屬性名字     namestring += name[props]; } alert(namestring);  //NAME1NAME2NAME3NAME4   delete name.name1;  //刪除name1屬性 delete name["name3"];  //刪除name3屬性 namestring = ""; for(var props in name) {  //循環name對象中的屬性名字     namestring += name[props]; } alert(namestring);  //NAME2NAME4   alert("name1" in name); //false alert("name4" in name); //true

  

  接下來講講比較常見的數組對象是無序數據的集合,而數組則是有序數據的集合,數組中的數據(元素)通過索引(從0開始)來訪問,數組中的數據可以是任何的數據類型,數組本身仍舊是對象,創建數組可以用"[]"操作符,或者是用Array()構造函數來new一個。

var array1 = [];  //創建空數組
var array2 = new Array();  //創建空數組
array1 = [1,"s",[3,4],{"name1":"NAME1"}]; //
alert(array1[2][1]);  //4   訪問數組中的數組元素
alert(array1[3].name1); //NAME1 訪問數組中的對象
alert(array1[8]);   //undefined
array2 = [,,];  //沒有數值填入只有逗號,則對應索引處的元素為undefined
alert(array2.length); //3
alert(array2[1]);     //undefined

  需要注意的是var array = new Array(10);初始化的長度10實際上對數組沒有任何的約束力,數組的長度是可以任意改變的。

  delete操作符刪除數組的元素,注意這個刪除僅僅是將數組在該位置的元素設為undefined數組的長度並沒有改變

var array = new Array("n1","n2","n3","n4","n5");  //五個元素的數組
var astring = "";
for(var i=0; i<array.length; i++) {           //循環數組元素
    astring += array[i];
}
alert(astring);       //n1n2n3n4n5
delete array[3];                   //刪除數組元素的值
alert(array.length + "_" + array[3])  //5_undefined
 
array.length = 3;    //縮減數組的長度
alert(array[3]);     //undefined
array.length = 8;    //擴充數組的長度
alert(array[4]);     //undefined

 

對象中也離不開函數,那如何創建函數:
  function f(x) {........}
  var f = function(x) {......}
上面這兩種形式都可以創建名為f()的函數,不過后一種形式可以創建匿名函數。

  方法的調用需要對象的支持,那么在方法中如何獲取對象的屬性呢?this!this關鍵字我們已經很熟悉了,在javascript的方法中,我們可以用this來取得對方法調用者(對象)的引用,從而獲取方法調用者的各種屬性。

var obj = {"name":"NAME","sex":"female"};
obj.print = function() {  //為對象添加方法
    alert(this.name + "_" + this["sex"]);
};
obj.print();  //NAME_female
obj.sex = "male";
obj.print();  //NAME_male

 

來一個更加面向對象的例子。

var person = {name:"defaultname",
              setName:function(s){
              this.name = s;
          },
          "printName":function(){
              alert(this.name);
          }}
person.printName();       //defaultname
person.setName("newName");
person.printName();       //newName

 

  下面更深入點,每一個函數都包含了一個原型(prototype),我們可以簡單的把prototype看做是一個模版,新創建的自定義對象都是這個模版(prototype)的一個拷貝。

通過prototype創建自定義對象的一個例子:

// 構造函數
        function Person(name, sex) {
            this.name = name;
            this.sex = sex;
        }
        // 定義Person的原型,原型中的屬性可以被自定義對象引用
        Person.prototype = {
            getName: function() {
                return this.name;
            },
            getSex: function() {
                return this.sex;
            }
        }

創建自定義對象(實例化類)

var zhang = new Person("ZhangSan", "man");
console.log(zhang.getName());   // "ZhangSan"

當代碼var zhang = new Person("ZhangSan", "man")執行時,其實內部做了如下幾件事情:

    1. 創建一個空白對象(new Object())。
    2. 拷貝Person.prototype中的屬性(鍵值對)到這個空對象中(我們前面提到,內部實現時不是拷貝而是一個隱藏的鏈接)。
    3. 將這個對象通過this關鍵字傳遞到構造函數中並執行構造函數
    4. 將這個對象賦值給變量zhang。

  上面我們提到了用new來創建一個對象的過程,事實上在這個過程中,當創建了空對象后,new會接着操作剛生成的這個對象的prototype屬性。
  每個方法都有一個prototype屬性(因為方法本身也是對象),new操作符生成的新對象的prototype屬性值和構造方法的prototype屬性值是一致的。構造方
法的prototype屬性指向了一個prototype對象,這個prototype對象初始只有一個屬性constructor,而這個constructor屬性又指向了prototype屬性所在的方
法。有點暈,看下面的圖:

  這樣,當用構造函數創建一個新的對象時,它會獲取構造函數的prototype屬性所指向的prototype對象的所有屬性。對構造函數對應的prototype對象所做的任何操作都會反應到它所生成的對象身上,所有的這些對象共享構造函數對應的prototype對象的屬性(包括方法)。
看個具體的例子吧:

function Person(name,sex) {  //構造函數
    this.name = name;
    this.sex = sex;
}
Person.prototype.age = 12;   //為prototype屬性對應的prototype對象的屬性賦值
Person.prototype.print = function() { //添加方法
    alert(this.name+"_"+this.sex+"_"+this.age);
};
 
var p1 = new Person("name1","male");
var p2 = new Person("name2","male");
p1.print();  //name1_male_12
p2.print();  //name2_male_12
 
Person.prototype.age = 18;  //改變prototype對象的屬性值,注意是操作構造函數的prototype屬性
p1.print();  //name1_male_18
p2.print();  //name2_male_18

  在javascript中,所有的方法都有一個call方法和apply方法。這兩個方法可以模擬對象調用方法,它的第一個參數是對象,后面的參數表示對象調用這個方法時的參數。概念比較拗口,平時很少遇到,所以用得少,比較難得理解這里就不作過多的講解了,請自行查找說得更明了的文章來了解吧。

  以上示例部分整理於園友文章,用得比較明了所以拿來講解,以上知識點可能只有在大家實際項目中運用的時候發現問題了,然后再來看,這時理解會更深入點,收藏起來作個備忘吧,有些源碼等知識可進入園友公眾號【一個碼農的日常】自行查看。

  再來一次前后照應,連JS都有對象,你為什么沒有?!!!(說好的不要打臉……)

 


免責聲明!

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



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