深刻javascript之對象

OOP

前言

這是讀書筆記第二篇,看完以後忽然發現本身對js的內置的一些東西仍是瞭解的不夠全面,不少方法見都沒見過,啥用都不知道,這是很是不可取的。碼農好歹也得眼熟啊,曉都不曉得後面的學習還怎麼進行下去。。。趕忙作筆記吧~文中若有錯誤不當不出,歡迎指出~vue

建立一個對象

var obj = {}  //字面量建立
var obj = new Object()  //構造函數建立

2種建立方式是徹底同樣的,通常書寫咱們都採用字面量。git

複製對象

首先明確一點,借用紅寶書一句話,對於對於js中的賦值傳參等操做,傳遞的都是值,不關是基本類型仍是引用類型,傳遞的都是值,只是引用類型傳遞的是一個內存地址的值。不一樣對象若是引用同一塊內存地址,仍是會相互影響的。對象就是引用類型,這裏介紹2種簡單的方法來複制對象,又能不相互影響。es6

//安全的json序列對象,只能複製鍵值對,不能複製函數

JSON.parse(JSON.stringify(obj))


//es6新增的內置方法複製對象


Object.assign({},obj1,obj2...)

對象屬性的特性

通常咱們看到的對象就是一對對鍵值對,其實內部並無咱們想象的這麼簡單。看如下代碼:github

var a = {
            a:2,
            fuc:function() {    
            console.log('xxx')
            }
        }
        
        //經過Object.getOwnPropertyDescriptors獲取對象屬性
        Object.getOwnPropertyDescriptors(a)
        a: {
        configurable: true  //可配置
        enumerable: true  //可枚舉
        value: 2
        writable: true // 可寫
        }
        .....

咱們看到a屬性除了一個值外,還有3個默認特性,繼續看:編程

var myObject = {};

Object.defineProperty( myObject, "a", {
    value: 2,
    writable: false, // not writable! 
    configurable: true,
    enumerable: true
} );

myObject.a = 3;

myObject.a; // 2

經過Object.defineProperty定義了一個a屬性,該屬性不可寫,結果上咱們已經沒法修改屬性值。json

var myObject = { 
    a:2
};

myObject.a; // 2

delete myObject.a; 
myObject.a; // undefined

Object.defineProperty( myObject, "a", {
    value: 2,
    writable: true, 
    configurable: false, 
    enumerable: true
} );

myObject.a; // 2 
myObject.a = 5; 
myObject.a; // 5


delete myObject.a; 
myObject.a; // 5

設置屬性不可配置,咱們看到咱們沒法再刪除這個屬性,可是仍然能夠修改值。enumerable特性咱們就比較熟悉了,for in循環枚舉屬性就是枚舉可枚舉的屬性,若是咱們設置爲false ,這個屬性就不會被枚舉。設計模式

要注意有一個小小的例外:即使屬性是configurable:false, 咱們仍是能夠把writable的狀態由true改成false,可是沒法由false改成true。數組

自定義屬性的set和get

var myObject = {
    // 給 a 定義一個getter
    get a() {
        return this._a_; 
    },

    // 給 a 定義一個setter
    set a(val) {
        this._a_ = val * 2;
    } 
};

myObject.a = 10 ;
myObject.a   //20

上面代碼咱們複寫了a屬性的獲取和設置方法,沒有賦值直接獲取會返回undefined,經過這個可使咱們創造出一些有趣的東西,vue源碼中咱們就能看到不少實際的例子。安全

propertyIsEnumerable(..)會檢查給定的屬性名是否直接存在於對象中(而不是在原型鏈上)而且知足enumerable:true。數據結構

Object.keys(..)會返回一個數組,包含全部可枚舉屬性,Object.getOwnPropertyNames(..)會返回一個數組,包含全部屬性,不管它們是否可枚舉。

in和hasOwnProperty(..)的區別在因而否查找[[Prototype]]鏈,然而,Object.keys(..)和Object.getOwnPropertyNames(..)都只會查找對象直接包含的屬性。

內置方法這裏再也不贅述,實時瞭解ecmascript的動態,掌握新的內容是很是必要的,咱們可能永遠用不到一些內置方法,可是咱們確保得先知道它,否則在須要的時候可能會像無頭蒼蠅亂撞或者使用一些比較蠢的老方法。

面向對象編程

什麼是面向對象編程?這個問題是我入坑時沒法解惑的一個問題。可是隨着業務的不斷積累,這個問題會變得愈來愈清晰。

咱們首先會介紹面向類的設計模式:實例化(instantiation)、繼承(inheritance)和(相對)多態(polymorphism)。

類理論

類/繼承描述了一種代碼的組織結構形式——一種在軟件中對真實世界中問題領域的建模方法。

面向對象編程強調的是數據和操做數據的行爲本質上是互相關聯的(固然,不一樣的數據有不一樣的行爲),所以好的設計就是把數據以及和它相關的行爲打包(或者說封裝)起來。這在正式的計算機科學中有時被稱爲數據結構。

舉例來講,用來表示一個單詞或者短語的一串字符一般被稱爲字符串。字符就是數據。可是你關心的每每不是數據是什麼,而是能夠對數據作什麼,因此能夠應用在這種數據上的行爲(計算長度、添加數據、搜索,等等)都被設計成String類的方法。

全部字符串都是String類的一個實例,也就是說它是一個包裹,包含字符數據和咱們能夠應用在數據上的函數。

咱們還可使用類對數據結構進行分類,能夠把任意數據結構看做範圍更廣的定義的一種特例。

咱們來看一個常見的例子,「汽車」能夠被看做「交通工具」的一種特例,後者是更普遍的類。

「在咱們的軟件中,對不一樣的交通工具重複定義「載人能力」是沒有意義的。相反,咱們只在Vehicle中定義一次,定義Car時,只要聲明它繼承(或者擴展)了Vehicle的這個基礎定義就行。Car的定義就是對通用Vehicle定義的特殊化。

雖然Vehicle和Car會定義相同的方法,可是實例中的數據多是不一樣的,好比每輛車獨一無二的VIN(Vehicle Identification Number,車輛識別號碼),等等。

這就是類、繼承和實例化。

類的另外一個核心概念是多態,這個概念是說父類的通用行爲能夠被子類用更特殊的行爲重寫。實際上,相對多態性容許咱們從重寫行爲中引用基礎行爲。

'類'設計模式

你可能歷來沒把類做爲設計模式來看待,討論得最多的是面向對象設計模式,好比迭代器模式、觀察者模式、工廠模式、單例模式,等等。從這個角度來講,咱們彷佛是在(低級)面向對象類的基礎上實現了全部(高級)設計模式,彷佛面向對象是優秀代碼的基礎。

考慮到儘量容易理解。這裏摘錄了基本概念,這是一個抽象的東西,咱們在擼碼過程當中可能不知不覺就已經在實踐這種理念,可是沒有看過這種概念的人可能會一會兒說不出來。

這些概念實際上沒法直接對應到JavaScript的對象機制,所以JavaScript開發者用一系列方法去模擬實現面相編程,好比混入,mixin。

這裏說說在下對面相對象編程的理解 ,面向對象編程其實就是一類事物的抽象。好比 人,都會說話,走路,可是可能有的人說漢語,有的人說英語,對於這種普遍的抽象中又有很是多的特例,咱們能夠對其建模:

var Person = function(){ 
this.name = 'person',
this.age = '',
this.talk = function(){alert('talk')},
this.walk = function(){alert('wall')}
}
var p1 = new Person()
var p2 = new Person()

p1.name = 'xu'
p2.name = 'pp'
...

咱們構造了一個person函數,經過person函數構造了2我的類實例,一個名字是xu一個名字是pp。。會說話,會走路。

ES6中的class語法

class Animal { 
  constructor(name) {
    this.name = name;
  }
  
  speak() {
    console.log(this.name + ' makes a noise.');
  }
}

class Dog extends Animal {
  speak() {
    console.log(this.name + ' barks.');
  }
}

var d = new Dog('Mitzie');
// 'Mitzie barks.'
d.speak();

es6的class語法糖讓咱們模擬面相編程變得更加規範,這裏引用mdn的一個例子,更具體的建議能夠本身找文章看,畢竟這是一個js一個很是重要的知識。

後記

要想徹底搞懂一些概念,抽象的東西,其實並非一天兩天,一兩篇文章就能作到的,個人建議是,理論,實踐,理論,實踐,一個螺旋上升的過程。感受筆記內容不是很深刻,畢竟是讀書筆記和本身的一些理解見解,就當深刻的程度不是那麼深吧~

若是以爲本文對你有所幫助,就star一下吧~大傳送之術! 個人博客Github

相關文章
相關標籤/搜索