【JS】14--js對象、json對象

JS對象介紹

前置知識
關于使用對象,可以先閱讀一下我的《11.使用對象》這篇文章。

#1.概念

對象是一個包含相關數據和方法的集合,由變量方法組成,通常稱為對象的屬性方法,比如:

let me = {
    name : 'pingan',
    eat: function(){
        console.log('eat eat eat!!!');
    }
}

其中,name就是me這個對象的一個屬性,eat就是me這個對象的一個方法。
訪問對象的屬性是這樣的:

me.name;   // "pingan"
me.eat();  // "eat eat eat!!!"

另外在訪問對象屬性時,有以下兩種方式:

let me = {
    name : 'pingan',
}
// 點表示法
me.name;   // me.name => "pingan"

// 括號表示法
me["name"];// me.name => "pingan"

括號表示法中,必須是字符串。

我們常常這么設置對象的屬性:

let me = {
    name : 'pingan',
}
// 點表示法
me.name = "leo";   // me => {name: "leo"}

// 括號表示法
me["name"] = "leo";// me => {name: "leo"}

#2.簡單的面向對象介紹

這里簡單介紹下JavaScrip的面向對象編程OOP。

面向對象編程(Object Oriented Programming,OOP,面向對象程序設計)是一種計算機編程架構。OOP 的一條基本原則是計算機程序是由單個能夠起到子程序作用的單元或對象組合而成。 —— 百度百科

OOP

我們這里定義一個簡單的對象模型,比如我,我的身上可能有很多信息(姓名,年齡,身高等等),這時候我們可以將這些信息抽取出來,像這樣:

let leo = {
    name : 'leo',
    age  : 26,
    height : 180,
}

這樣我們就將我的信息抽取成一個JS的對象了,但是這樣有個局限性,這樣定義的話,一次只能定義一個人,如果這時候,有一百個人,那么我們就需要定義一百個這樣的對象,顯然這是不可取的。
所以,這里就引入一個重要的函數——構造函數將相同的特性封裝成通用的對象,實現定義一次,其他地方都可以使用,這也是OOP的核心思想:

// 傳入 name 參數使得可以定義任何人作為對象
function Person (name){
    let me = {};
    me.name = name;
    me.doSomething = function(){
        console.log(me.name);
    }
    return me;
}

創建一個函數“Person”,只要傳入不同的name即可得到不同的對象:

let leo = Person("leo");
leo.name;    // "leo"

let pingan = Person("pingan");
pingan.name; // "pingan"

但是似乎Person對象的定義,顯得不夠精簡,因為還要定義一個空對象來接收各個屬性和方法,幸好JavaScrip在構造函數中提供一個便捷的方法,我們將代碼改造下:

function Person (name){
    this.name = name;
    this.doSomething = function(){
        console.log(this.name);
    }
}

對于this關鍵詞,即無論是該對象的哪個實例被構造函數創建,它的name屬性都是參數name的值,doSomething方法中使用的也是參數name。簡單理解就是用this指代了Person

構造函數通常首字母大寫,用于區分普通函數。

接下來,通過new關鍵詞,使用前面創建的構造函數(使用構造函數也叫實例化):

let leo = new Person("leo");
leo.name;    // "leo"

let pingan = new Person("pingan");
pingan.name; // "pingan"

然后一個簡單的構造函數就寫好了,通常在開發的時候,可能會有很多的參數:

function Man(name, age, height, weight){
    this.name = name;
    this.age = age + '歲';
    this.HeightAndWeight = {
        height,
        weight
    };
    this.doSomething = function (){
        console.log(`
            ${this.name}: height:${this.HeightAndWeight.height}m, 
            weight:${this.HeightAndWeight.weight}Kg!!`
        );
    };
}

let leo = new Man("leo",25,1.8,68);
leo.doSomething();  // leo: height:1.8m, weight:68Kg!!

#3.JS中的原型

#3.1理解原型

這里需要先了解一下ObjectFunction,這兩個函數都是JS的自帶函數,Object繼承自己,Function繼承自己,相互繼承對方,即ObjectFunction既是函數也是對象。

console.log(Function instanceof Object); // true
console.log(Object instanceof Function); // true

ObjectFunction的實例,而Function是它自己的實例。

console.log(Function.prototype); // ? () { [native code] }
console.log(Object.prototype);  // Object

另外,只有通過Function創建的函數都是函數對象,其他都是普通對象(通常由Object創建):

function f1(){};
typeof f1 //"function"

var o1 = new f1();
typeof o1 //"object"

var o2 = {};
typeof o2 //"object"

理論知識:

JavaScript 常被描述為一種基于原型的語言 (prototype-based language)——每個對象擁有一個原型對象,對象以其原型為模板、從原型繼承方法和屬性。
原型對象也可能擁有原型,并從中繼承方法和屬性,一層一層、以此類推。這種關系常被稱為原型鏈(prototype chain),它解釋了為何一個對象會擁有定義在其他對象中的屬性和方法。
準確地說,這些屬性和方法定義在Object的構造器函數(constructor functions)之上的prototype屬性上,而非對象實例本身。

個人理解:

  • JS中所有的函數對象,都有一個prototype屬性,對應當前對象的原型,但普通對象沒有,而prototype屬性下還有一個constructor,指向這個函數。
var p = {};
p.prototype;         // undefined
p instanceof Object; // true

function f (){}; 
f.prototype;         // object {constructor: ?}
f === f.prototype.constructor;           // true
Object === Object.prototype.constructor; // true

  • JS中所有的對象,都有一個_proto_屬性,指向實例對象的構造函數原型(由于_proto_是個非標準屬性,因此只有ffchrome兩個瀏覽器支持,標準方法是Object.getPrototypeOf())。
var p = new Person(); 
p._proto === Person.prototype;  //true

修改原型:
經常我們也需要對原型進行修改:

function Person (name){
    this.name = name;
}
// 添加一個getName方法
Person.prototype.getName = function(){
    return "名字:" + this.name;
}
var p = new Person("leo"); 
p.getName();   // "名字:leo"

這里也說明了原型進行繼承,p繼承Person原型中新增的函數屬性getName

#3.2原型鏈

概念:
javascript中,每個對象都會在內部生成一個 proto 屬性,當我們訪問一個對象屬性時,如果這個對象不存在就回去 proto 指向的對象里面找,一層一層找下去,,知道找到為止,如果到了原型鏈頂端,還沒找到,則返回undefined,這就是javascript原型鏈的概念。

原型鏈:

總結:

  • 除了Objectprototype的原型是null,所有對象和原型都有自己的原型,對象的原型指向原型對象。
  • JS中所有的東西都是對象,所有的東西都由Object衍生而來, 即所有東西原型鏈的終點指向null。

更加詳細的介紹,可以查看下面參考文章。


#參考文章

1.MDN JavaScript 對象入門

2.基于js中的原型

2.JSON對象介紹

前置知識
JSON是一種按照JavaScript對象語法的數據格式。

#1.概念

概念有三點:

JSON全稱JavaScript 對象表示法(JavaScript Object Notation)。
JSON存儲交換文本信息的語法。類似 XML
JSONXML 更小、更快,更易解析。
———— 摘自 W3school JSON教程

JSON 使用 JavaScript 語法來描述數據對象,但是 JSON 仍然獨立于語言和平臺。JSON 解析器和 JSON 庫支持許多不同的編程語言。

#2.語法

JSON在使用過程中可作為一個對象或者字符串存在,當作為對象時,用于獲取JSON中的數據,而作為字符串時常用于網絡數據傳輸。

JSON語法規則:

  1. 數據在名稱/值對中
  2. 數據由逗號分隔
  3. 花括號保存對象
  4. 方括號保存數組

通常,JSON數據書寫格式是名稱/鍵值

"name" : "pingan"

JSON的值可以是 :

  1. 數字(整數或浮點數)
  2. 字符串(在雙引號中)
  3. 邏輯值(truefalse
  4. 數組(在方括號中)
  5. 對象(在花括號中)
  6. null

JSON常常有三種類型:
三種類型:簡單之,對象和數組。
必須注意:JSON字符串必須是雙引號,單引號會語法錯誤。

#2.1 簡單值

簡單值可以是字符串:

"hello leo!"

也可以是數字,邏輯值:

1

#2.2 對象類型

內容放在花括號內,是多個鍵值對。
JSON對象 與 js 對象的三個區別:

  1. JSON對象 必須加雙引號,而 js 對象屬性名可以不加雙引號。
  2. JSON對象 沒有變量聲明,而 js 對象有。
  3. JSON對象 沒有分號,而 js 對象有。
// js 對象
var obj = {
    name : "pingan",
    age  : "25",
};
// json 對象
{
    "name" : "pingan",
    "age"  : "25",
    "box"  : [
        "a","b","c"
    ]
}

#2.3 數組類型

內容放在方括號內。
JSON數組也沒有分號和變量,常常可以把JSON數組和對象結合使用,構成更復雜的數據集合。

[
    {
        "name" : "leo",
        "age"  : 25,
        "box"  : ["a","b","c"]
    },
    {
        "name" : "pingan",
        "age"  : 25,
        "box"  : ["a","b","c"]
    }
]

#3. 使用

JSON最常見的用法就是,從服務端獲取JSON數據,再將JSON數據轉成JavaScrip對象使用。
JSON對象有兩個方法:

  • JSON.stringify(): 序列化操作,將JavaScript對象轉換成JSON字符串
  • JSON.prase():反序列化操作,將JSON字符串解析成JavaScript值

#3.1 序列化操作

序列化操作常常使用JSON.stringify()
簡單例子:

let leo =  {
    name : "leo",
    age  : 25,
    box  : ["a","b","c"]
}
let pingan = JSON.stringify(leo);
console.log(pingan); // "{"name":"leo","age":25,"box":["a","b","c"]}"

注意

  1. 默認情況下,JSON.stringify()輸出的JSON字符串不包含任何空格字符或縮進,因此結果就像上面那樣。
  2. 序列化JavaScript對象時,所有函數及原型成員都會被忽略,不體現在結果上。
  3. 值為undefined的任何屬性都會被跳過。

因此,最終的值都是有效的JSON數據類型的實例屬性。

#3.2 反序列化操作

序列化操作常常使用JSON.parse()
簡單例子:

let copyPingan = JSON.parse(pingan);
copyPingan; // {name: "leo", age: 25, box: Array(3)}

如果傳入JSON.parse()的字符串不是有效的JSON,則會拋出錯誤。
注意
雖然pingancopyPingan屬性相同,但兩者獨立,沒有任何關系。

#4.序列化選項

JSON.stringify()除了要傳入序列化對象作為參數,還可以接收其他兩個參數,用來指定序列化JavaScript對象的方式:

  1. 過濾器:可以是個數組,也可以是個函數
  2. 選項:表示是否在JSON字符串保留縮進

單獨或組合使用兩者,可以更加全面深入的控制JSON的序列化。

#4.1 過濾器

若過濾器的參數是數組,則JSON.stringify()返回的結果將只包含數組中的屬性:

var leo =  {
    name : "leo",
    age  : 25,
    box  : ["a","b","c"]
}
var pingan = JSON.stringify(leo,["name","age"]);
console.log(pingan); // "{"name":"leo","age":25}"

若過濾器的參數是函數,則情況就不一樣了,傳入的函數需有兩個參數(屬性名和屬性值):

var leo =  {
    "name" : "leo",
    "age"  : 25,
    "box"  : ["a","b","c"]
}
var pingan = JSON.stringify(leo,function(key, value){
    switch(key){
        case "name":
            return "我叫" + value
        case "age":
            return value + "歲"
        default:
            return value
    }
});
console.log(pingan); // "{"name":"我叫leo","age":"25歲","box":["a","b","c"]}"

注意:使用switch的時候,必須指定default否則會返回undefined

#4.2 選項

JSON.stringify()第三個參數是個選項,控制結果中的縮進和空白符。

  1. 若選項只有一個值,則表示每個級別縮進的空格數,最大值為10,超過10則只會是10
var leo =  {
    "name" : "leo",
    "age"  : 25,
    "box"  : ["a","b","c"]
}
var pingan = JSON.stringify(leo, null, 4);
console.log(pingan);
/*
"{
    "name": "leo",
    "age": 25,
    "box": [
        "a",
        "b",
        "c"
    ]
}"
*/

[#]5.解析選項

JSON.parse()可以接收一個函數作為參數,對每個鍵值對調用,為了跟JSON.stringify()過濾函數區別,這個函數成為還原函數

  • 若還原函數返回undefined,則表示要從結果中刪除對應的鍵。
  • 若還原函數返回其他值,則將該值插入結果中。

還原函數接收兩個參數:屬性名和屬性值。

舉例,在日期字符串轉換為Date對象中,經常要用到還原函數:

var leo =  {
    "name" : "leo",
    "age"  : 25,
    "date" : new Date(1993, 9, 9)
}
var pingan = JSON.stringify(leo);
var copy = JSON.parse(pingan,function (key, value){
    // return key == "date" ? new Date(value) : value;
    if(key == "date"){
        return new Date(value);
    }else{
        return value; 
    }
})
console.log(copy);
// "{"name":"leo","age":25,"date":"1993-10-08T16:00:00.000Z"}"

var obj = {
            name:"mumu",
            age:18,
            money:null,
            say:function(){alert("babababa")},
            family:["爸爸","媽媽","哥哥","姐姐"]
        }
        var str = JSON.stringify(obj);
        // 將javascript 對象轉換為JSON字符串;
        console.log(str);
        // 把字符串 轉換為javascript 對象
        var obj2 = JSON.parse(str);
        console.log(obj);
        console.log(obj2);

[#]參考文章

  1. W3school JSON教程
  2. 《JavaScrip高級程序設計》
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,156評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,401評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,069評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,873評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,635評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,128評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,203評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,365評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,881評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,733評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,935評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,475評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,172評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,582評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,821評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,595評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,908評論 2 372

推薦閱讀更多精彩內容