JS--我發現,原來你是這樣的JS:面向對象編程OOP[2]--(建立你的那個對象吧)

1、介紹

咱們繼續面向對象吧,此次是面向對象編程的第二篇,主要是講建立對象的模式,但願你們能從博客中學到東西。
時間過得很快,仍是不斷的學習吧,爲了本身的目標。html

2、建立對象

1.前面的建立對象方式

a.在前面的章節中,咱們建立對象的方式有兩種:new Object() 和 對象字面量:

//1.new Object() 建立對象
var person1 = new Object();
person1.name = "ry";
person1.age = 21;

//2.對象字面量
var person2 = {
    name : "ry",
    age : 1
};

不足:前面這兩種方法是能建立對象,可是有個不足就是,要建立不少對象時會有不少重複的代碼,好比我再創個person3,又要打一次上面大部分的代碼。
因此:做爲一個有志青年,咱們有下面的解決方法,使用工廠模式。編程

2.工廠模式

工廠模式:聲明一個函數,它封裝了以特定接口建立對象的細節,並返回一個具體對象。數組

a.透過代碼看工廠函數

//工廠模式,聲明一個工廠函數
funtion createPerson(name,age){
    //建立一個對象
    var obj = new Object();
    //對對象屬性賦值
    obj.name = name;
    obj.age = age;
    obj.sayHi = {
        console.log("Hi");
    };
    //返回對象
    return obj;
};

//咱們一會兒就建立了3個對象
var p1 = createPerson("ry", 30);
var p2 = createPerson("淵源遠願",31);
var p3 = createPerson("阿元",21);

console.log(p1.name);  //"ry"
console.log(p2.age);  // 30
p2.sayHi();  //"Hi"
p3.sayHi();  //"Hi"

b.俗話說說工廠函數

  • 上面咱們的例子是建立人的工廠函數,咱們能夠一次建立不少人了,而不用像第一種方法同樣寫不少的重複代碼。就這麼先進,就像工廠同樣。
  • 可是,工廠模式仍是不足,他不能標識出這個對象屬於什麼類型。通俗點說就是,工廠函數只能說明你是對象,可是你是人,仍是貓,仍是豬,這個咱們不知道。

因此:做爲一個有志青年,咱們有下面的解決對象識別的方法,即便用構造函數模式。瀏覽器

3.構造函數模式

構造函數咱們之前有據說過,好比建立數組時的Array(),建立時間的Date(),接下來咱們也能夠自定義本身的構造函數了。函數

a.透過代碼看構造函數

//Dog 構造函數,構造函數用個大寫字母開頭,以便和普通函數區分一下
function Dog (name , age ){
    this.name = name;
    this.age = age;
    this.sayHi = function(){
        console.log("Hi");
    };
}

//使用構造函數建立對象,3只狗狗
var dog1 = new Dog('lucy' , 1);
var dog2 = new Dog('Jack' , 2);
var dog3 = new Dog('Mc' , 3);

b.俗話說說構造函數

1.所謂"構造函數",其實就是一個普通函數,可是內部使用了this變量。
2.對構造函數使用new運算符,就能生成實例(就是這麼先進),而且this變量會綁定在實例對象上。學習

▶比工廠模式好在這裏:由於使用構造函數建立對象時對象實例會有一個constructor屬性(構造函數屬性),指向他的構造函數,那咱們就知道這個對象是人,仍是貓,仍是小豬了。測試

那就用代碼說明一下this

//上面的建立的3只狗狗:dog1,dog2 ,dog3,看看他們的constructor屬性
console.log(dog1.constructor == Dog) //true
console.log(dog2.constructor == Dog) //true
console.log(dog3.constructor == Dog) //true

//用instanceof 測試一下 
//instanceof做用是測試某對象是否是某個類型。不記得就看看前面的博客哦
console.log(dog1 instanceof Dog); //true
console.log(dog2 instanceof Dog); //true
console.log(dog3 instanceof Dog); //true
console.log(dog3 instanceof Object); //true  固然也是一個object類型

可是,構造函數仍是有不足的地方,好比上面你們都有一個sayHi函數(每一個對象共有的),咱們知道函數就是一個對象,在咱們每一次建立一個對象時都須要從新的建立sayHi函數,這會浪費內存空間,因此咱們要考慮把這個函數設置成共享的(只建立一次你們一塊兒用)。
因此,做爲一個有志青年,咱們看看原型模式prototype

4.原型模式(prototype模式)

a.先理解原型對象

1.首先咱們要先了解概念:不管何時,咱們建立的每個函數都有一個prototype屬性,它指向原型對象(自動生成的一個對象)。
2.原型對象的做用是包含由特定類型的全部實例共享的屬性和方法。(就是能保存讓對象共享的屬性和方法)。
你能夠這樣看的:若是你把原型對象理解成一個某類型的公共區域,也能夠的。code

//原型模式
function Pig(){ 
    //往Pig的原型對象添加屬性和方法
    Pig.prototype.name = "lucy";
    Pig.prototype.age = 2;
    Pig.prototype.sayHi = function(){console.log('hi')};
}
//建立對象
new pig1 = new Pig();
new pig2 = new Pig();
//你們都是共同的屬性和方法,共享了
console.log(pig1.name);  //"lucy"
console.log(pig2.name);  //"lucy"
pig1.sayHi();  //"hi"
pig2.sayHi();  //"hi"

console.log(pig1.sayHi == pig2.sayHi());  //true

上面的例子,咱們將Pig的屬性和方法都添加到了Pig.prototype(這就是原型對象了)中,因此由Pig建立的實例能共享這些屬性方法。

咱們看圖來了解構造函數原型對象對象實例之間的關係:
1.構造函數有prototype屬性指向原型對象
2.原型對象有個constructor屬性指回構造函數
3.每一個對象實例有個_proto_屬性(瀏覽器支持的)指向原型對象

原型對象的出現,爲了存放,對象實例的共享的屬性和方法。

b.一些經常使用的方法

  • isPrototypeOf() 來檢測對象的原型和原型對象是否有關係
//測試一下pig1的原型對象是否是Pig.prototype
console.log(Pig.prototype.isPrototypeOf(pig1)) // true
  • Object.getPrototypeOf() 獲取對象實例的原型對象(ES5新增的方法)。兼容性:IE9+
console.log(Object.getPrototypeOf(pig1) == Pig.prototype);  //true
  • hasOwnProperty(),用來肯定訪問的屬性在不在對象實例自己
//爲pig1重寫name屬性,該屬性就會在實例自己。
pig1.name= "bigPig";
//hasOwnPrototype 做用是問name屬性在對象實例本身身上嗎,是就返回true
console.log(pig1.hasOwnPrototype(name));  //true

//對於pig2,咱們沒有在對象實例中重寫name,因此它的name屬性源於原型對象,而不在pig2自己裏面
console.log(pig2.hasOwnPrototype(name));  //false
  • hasPrototypePorperty(),用來肯定訪問的屬性在不在原型對象中
//很明顯這個方法和上面的hasOwnProperty是相對的
//在對象自己重寫name,因此name在對象自己
pig.name = "bigPig";
//詢問pig1中的name屬性是否是在原型對象中
console.log(hasPrototypePorperty(pig1,"name"));  //false
//詢問pig2中的name屬性是否是在原型對象中,pig2沒有重寫name,因此在原型對象中
console.log(hasPrototypePorperty(pig2,"name"));  //true
  • in操做符 做用:直接問對象中有沒有某某屬性,不管在對象實例本事仍是在原型對象中,只要有就返回true,不然false
//pig1 有name屬性
console.log("name"  in pig1);  //true
//pig1 中沒有weight 屬性
console.log("weight" in pig1);  //false
  • for-in 做用:用來遍歷某個對象的全部屬性
function Car (){
    Car.prototype.name = "ryuan",
    Car.prototype.color = "red"
}
var car1 = new Car();
for(var prop in car1){
    console.log(prop);
}
//輸出:
name
color
  • Object.keys() 做用:取得對象全部可枚舉的屬性。接受一個對象做爲參數,返回對象屬性的數組。(ES5的方法)
function Car (){
    Car.prototype.name = "ryuan",
    Car.prototype.color = "red"
}
console.log(Car.prototype);  //["name", "color"]

c.更簡單的原型對象語法

由於原型對象也是個對象,因此咱們能夠這樣簡便的定義原型對象。固然也是爲了偷懶少打些代碼,哈哈哈。優雅點,簡單點,敲代碼的方式簡單點。

function Person(){};
//Person構造函數的原型對象,簡單寫法
Person.prototype = {
    name : "ry",
    age : 21,
    sayHi : function(){
        console.log("hi");
    }
};

不足:這種寫法也有很差的地方,就是這樣寫至關於重寫了Person的原型對象。原型對象的constructor屬性就再也不指向Person了。

//好比
var p1 = new Person();
console.log(p1.constructor == Person);  //false

//可是instanceof仍是可以判斷對象是否是某類型
console.log(p1 instanceof Person);  //true

若是constructor很重要的請況下:能夠這樣加上去

Person.prototype = {
    //加上這行,也就是定義constructor
    constructor: Person,
    name : "ry",
    age : 21,
    sayHi : function(){
        console.log("hi");
    }
}

問題:原型模式只是一個共享區對吧,那我又要不共享的屬性,那怎麼辦?
因此:做爲一個有志青年,結合一下構造函數模式和原型模式吧。

5.組合使用構造函數模式和原型模式

這兩種模式的結合能夠說是最多用的,這是用來定義引用類型的默認方式。雙劍合璧。

1.構造模式用於定義實例屬性。
2.原型模式用來定義方法和共享的屬性。

function Person(name , age , sex){
    //這裏定義實例的屬性
    this.name = name ;
    this.age = age ;
    this.sex = sex;
}
//下面定義共享的屬性和方法
Person.prototype = {
    constructor : Person ,
    sayHi : function (){
        console.log("hi");
    }
}

//建立你的對象吧
var girl = new Person("玲玲",18,"female");
var boy = new Person ("元元",20,"male");

//各自的名字
console.log(girl.name);  //"玲玲"
console.log(boy.name);  //"元元"
//打招呼
girl.sayHi();  //hi
boy.sayHi();  //hi

3、說說

本次主要是怎麼去建立對象和怎麼去定義本身的引用類型。慢慢理解理解,慢慢吃透,歡迎你們一塊兒討論。
找不到對象,咱們仍是本身建立吧,哈哈哈。作個積極向上的人,對象總會有的。
不忘初心,方得始終。以爲博主寫得很好就贊一下吧,也能夠關注俺哦。

同系列前幾篇:
第一篇:JavaScript--我發現,原來你是這樣的JS(一)(初識)
第二篇:JavaScript--我發現,原來你是這樣的JS(二)(基礎概念--軀殼篇)
第三篇:JavaScript--我發現,原來你是這樣的JS(三)(基礎概念--靈魂篇)
第四篇:JavaScript--我發現,原來你是這樣的JS(四)(看看變量,做用域,垃圾回收是啥)
第五篇:JavaScript--我發現,原來你是這樣的JS(引用類型不簡單[上篇],且聽我娓娓道來)
第六篇:JavaScript--我發現,原來你是這樣的JS(引用類型不簡單[下篇],基本包裝類型與個體內置對象)
第七篇:JavaScript--我發現,原來你是這樣的JS:面向對象編程OOP[1]--(理解對象和對象屬性類型)

本文出自博客園:http://www.cnblogs.com/Ry-yuan/ 做者:Ry(淵源遠願) 歡迎轉載,轉載請標明出處,保留該字段。

相關文章
相關標籤/搜索