咱們繼續面向對象吧,此次是面向對象編程的第二篇,主要是講建立對象的模式,但願你們能從博客中學到東西。
時間過得很快,仍是不斷的學習吧,爲了本身的目標。html
//1.new Object() 建立對象 var person1 = new Object(); person1.name = "ry"; person1.age = 21; //2.對象字面量 var person2 = { name : "ry", age : 1 };
不足:前面這兩種方法是能建立對象,可是有個不足就是,要建立不少對象時會有不少重複的代碼,好比我再創個person3,又要打一次上面大部分的代碼。
因此:做爲一個有志青年,咱們有下面的解決方法,使用工廠模式。編程
工廠模式:聲明一個函數,它封裝了以特定接口建立對象的細節,並返回一個具體對象。數組
//工廠模式,聲明一個工廠函數 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"
因此:做爲一個有志青年,咱們有下面的解決對象識別的方法,即便用構造函數模式。瀏覽器
構造函數咱們之前有據說過,好比建立數組時的Array(),建立時間的Date(),接下來咱們也能夠自定義本身的構造函數了。函數
//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);
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
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_屬性(瀏覽器支持的)指向原型對象
原型對象的出現,爲了存放,對象實例的共享的屬性和方法。
//測試一下pig1的原型對象是否是Pig.prototype console.log(Pig.prototype.isPrototypeOf(pig1)) // true
console.log(Object.getPrototypeOf(pig1) == Pig.prototype); //true
//爲pig1重寫name屬性,該屬性就會在實例自己。 pig1.name= "bigPig"; //hasOwnPrototype 做用是問name屬性在對象實例本身身上嗎,是就返回true console.log(pig1.hasOwnPrototype(name)); //true //對於pig2,咱們沒有在對象實例中重寫name,因此它的name屬性源於原型對象,而不在pig2自己裏面 console.log(pig2.hasOwnPrototype(name)); //false
//很明顯這個方法和上面的hasOwnProperty是相對的 //在對象自己重寫name,因此name在對象自己 pig.name = "bigPig"; //詢問pig1中的name屬性是否是在原型對象中 console.log(hasPrototypePorperty(pig1,"name")); //false //詢問pig2中的name屬性是否是在原型對象中,pig2沒有重寫name,因此在原型對象中 console.log(hasPrototypePorperty(pig2,"name")); //true
//pig1 有name屬性 console.log("name" in pig1); //true //pig1 中沒有weight 屬性 console.log("weight" in pig1); //false
function Car (){ Car.prototype.name = "ryuan", Car.prototype.color = "red" } var car1 = new Car(); for(var prop in car1){ console.log(prop); } //輸出: name color
function Car (){ Car.prototype.name = "ryuan", Car.prototype.color = "red" } console.log(Car.prototype); //["name", "color"]
由於原型對象也是個對象,因此咱們能夠這樣簡便的定義原型對象。固然也是爲了偷懶少打些代碼,哈哈哈。優雅點,簡單點,敲代碼的方式簡單點。
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"); } }
問題:原型模式只是一個共享區對吧,那我又要不共享的屬性,那怎麼辦?
因此:做爲一個有志青年,結合一下構造函數模式和原型模式吧。
這兩種模式的結合能夠說是最多用的,這是用來定義引用類型的默認方式。雙劍合璧。
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
本次主要是怎麼去建立對象和怎麼去定義本身的引用類型。慢慢理解理解,慢慢吃透,歡迎你們一塊兒討論。
找不到對象,咱們仍是本身建立吧,哈哈哈。作個積極向上的人,對象總會有的。
不忘初心,方得始終。以爲博主寫得很好就贊一下吧,也能夠關注俺哦。
同系列前幾篇:
第一篇:JavaScript--我發現,原來你是這樣的JS(一)(初識)
第二篇:JavaScript--我發現,原來你是這樣的JS(二)(基礎概念--軀殼篇)
第三篇:JavaScript--我發現,原來你是這樣的JS(三)(基礎概念--靈魂篇)
第四篇:JavaScript--我發現,原來你是這樣的JS(四)(看看變量,做用域,垃圾回收是啥)
第五篇:JavaScript--我發現,原來你是這樣的JS(引用類型不簡單[上篇],且聽我娓娓道來)
第六篇:JavaScript--我發現,原來你是這樣的JS(引用類型不簡單[下篇],基本包裝類型與個體內置對象)
第七篇:JavaScript--我發現,原來你是這樣的JS:面向對象編程OOP[1]--(理解對象和對象屬性類型)
本文出自博客園:http://www.cnblogs.com/Ry-yuan/ 做者:Ry(淵源遠願) 歡迎轉載,轉載請標明出處,保留該字段。