摘要:創建對象什么是工廠模式封裝一個函數用來創建對象并給對象中特定的屬性添加值優點是可以循環調用缺點是每一個創建出來的對象都是獨立的不能確定它是哪個類型的對象或者說是想要將哪個對象作為模板進行創建每個對象都是獨立的并且指向的不能辨別基于哪個對象為
創建對象 什么是工廠模式 ?
封裝一個函數 , 用來創建對象并給對象中特定的屬性添加值 , 優點是可以循環調用 , 缺點是每一個創建出來的對象都是獨立的 , 不能確定它是哪個類型的對象 ( 或者說是想要將哪個對象作為模板進行創建 )
function func(name, age) { var o = { "name" : name, "age" : age }; return o; } var person = func("oswald", 24); var person2 = func("oswald", 24); // {name: "oswald", age: 24} console.log(person === person2); // false console.log(person.__proto__ === Object.prototype); // true console.log(person2.__proto__ === Object.prototype); // true // 每個對象都是獨立的并且指向 Object.prototype 的 , 不能辨別基于哪個對象為原型什么是構造函數模式 構造函數模式和工廠模式的區別
構造函數模式就是通過構造函數來創建自定義類型的對象 , 創建出來的對象都指向了同一個構造函數的 prototype , 解決了工廠模式中不能識別對象模板的問題
function Person(name, age) { this.name = name; this.age = age; this.sayName = function(){ console.log(this.name); }; /* 沒有顯式的創建對象 用 this 代替新對象 沒有 return 語句 */ } var person1 = new Person("oswald", 24); console.log(person1); // {name: "oswald", age: 24} console.log(person1.__proto__ === Person.prototype); // true // person1 指向了 構造函數 func.prototype console.log(person1 instanceof Person); // true // person1 對象是構造函數 Person ( 也可以叫做 Person 類型 ) 的實例 console.log(person1 instanceof Object); // true // person1 對象也是 Object 類型的實例構造函數模式的缺點
但是 , 上面的構造函數模式也不是沒有缺點的 : 單純的構造函數模式創建對象的時候 , 對象中每個方法都會在實例對象上重新創建一次 , 也就是說每次都會創建一個看起來相同但是完全不是一個"方法"的方法
function Person(name, age) { this.name = name; this.age = age; this.sayName = function(){ console.log(this.name); }; } var person1 = new Person("oswald", 24); var person2 = new Person("oswald", 24); console.log(person1.sayName = person2.sayName); // false // 每次創建對象的時候 , 都會生成一個功能一樣但是是不同 Function 實例的方法什么是原型模式
每個函數在創建的時候都會有一個 prototype 屬性 , 這個屬性指向一個對象
所有以這個函數為構造函數創建的實例對象 , 都會連接到構造函數的 prototype 屬性指向的這個對象上 , 并且可以訪問這個對象的所有屬性和方法 , 這個對象就叫做原型對象
原型對象在創建的時候自帶一個不可枚舉的 constructor 屬性 , 指向構造函數
function Person(){ Person.prototype.name = "oswald"; Person.prototype.age = 24; Person.prototype.sayName = function(){ console.log(this.name); }; } var person1 = new Person(); console.log(person1); // {} 得到一個空對象 , 因為創建的屬性和方法都在實例的原型對象上 console.log(Person.prototype); // {name: "oswald", age: 24, sayName: f(...)} console.log(person1.name); // oswald 得到一個名字 , 因為實例對象可以從它的原型對象上查找屬性和方法 var person2 = new Person(); console.log(person2.sayName === person1.sayName); // true // person1 和 person2 訪問的 sayName 方法都是原型對象上的方法 , 不是它們自身的 , 這樣就解決了構造函數模式多次創建方法實例的缺點原型對象中的屬性和方法會和實例對象自有的沖突嗎
如果當前實例對象中已經有了想要查找的屬性和方法 , 會直接使用實例對象的屬性和方法 , 如果沒有才去原型對象中查找
function Person(){ Person.prototype.name = "oswald"; Person.prototype.age = 24; } var person1 = new Person(); console.log(person1.name); // oswald person1.name = "yin"; console.log(person1.name); // yin實例對象怎么訪問原型對象
在火狐、谷歌等瀏覽器中提供了一個 __proto__ 的屬性 , 可以訪問它的原型對象
ECMAScript 5 中提供了 Object.getPrototypeOf( ) 方法可以檢測并返回它的原型對象
function Person(){ Person.prototype.name = "oswald"; Person.prototype.age = 24; } var person1 = new Person(); console.log(person1.__proto__ === Person.prototype); // true console.log(Object.getPrototypeOf(person1) === Person.prototype); // true原型對象和原型屬性有什么區別
實例對象 ( person1 ) 的原型對象 ( __proto__ ) 是創建當前對象的構造函數 ( Person ) 的原型屬性 ( prototype ) , 個人用來區別訪問途徑 , 便于理解
function Person(){ Person.prototype.name = "oswald"; Person.prototype.age = 24; } var person1 = new Person(); console.log(person1.__proto__ === Person.prototype); // true
實例對象可以查找它的原型對象 , 但是不能查找它自己的原型屬性
function Person(){ } var person1 = new Person(); person1.prototype = { name: "yin", age: 23 } console.log(person1.name); // undefined怎么檢測屬性或者方法在實例對象中是否存在
使用繼承自 Object 對象的 hasOwnProperty( ) 方法可以檢車要查找的屬性或方法是否來自實例對象而不是實例對象的原型對象
function Person(){ Person.prototype.name = "oswald"; Person.prototype.age = 24; } var person1 = new Person(); console.log(person1.name); // oswald console.log(person1.hasOwnProperty("name")); // false 當前查找到的 name 屬性來自原型對象 person1.name = "yin"; console.log(person1.name); // yin console.log(person1.hasOwnProperty("name")); // true 當前查找到的 name 屬性來自實例對象枚舉對象中的屬性和方法有哪些方法
for - in 遍歷 , 會將當前對象和當前對象的原型對象上所有可以枚舉的屬性和方法都返回
function Person(){ Person.prototype.name = "oswald"; Person.prototype.age = 24; } var person1 = new Person(); person1.color = "red"; for( poop in person1 ){ console.log(poop); // color, name, age }
ECMAScript 5 的 Object.key( ) 方法 , 遍歷當前對象的可枚舉屬性和方法 , 不會去找原型對象
function Person(){ Person.prototype.name = "oswald"; Person.prototype.age = 24; } var person1 = new Person(); person1.color = "red"; var p1keys = Object.key(person1); console.log(p1keys); // color
Object.getOwnPropertyNames( ) 方法 , 遍歷當前對象的所有屬性和方法 , 包括不可枚舉的 , 不會去找原型對象
function Person(){ Person.prototype.name = "oswald"; Person.prototype.age = 24; } var person1 = new Person(); person1.color = "red"; var p1keys = Object.getOwnPropertyNames(person1); console.log(p1keys); // color var Ppkeys = Object.getOwnPropertyNames(Person.prototype); console.log(Ppkeys); // constructor、name、age原型模式創建對象的缺點
原型中的所有屬性和方法都是共享的 , 如果有多個實例 , 通過其中一個實例改變原型對象中的屬性和方法 , 其他實例訪問的屬性會跟著改變
組合使用構造函數模式和原型模式將對象的私有屬性和方法通過構造函數模式創建 , 將對象的公共屬性和方法通過原型模式創建
function Person(name,age){ /* 私有屬性 */ this.name = name; this.age = age; } Person.prototype.sayName = function(){ /* 公共方法 */ console.log(this.name); } var person1 = new Person("oswald", 24); person1.sayName(); // oswald繼承 什么是原型鏈
原型鏈就是連接實例對象和原型對象的鏈接
/* 一般函數的原型鏈 */ function func(){ console.log(123); } console.log(func.__proto__); // Function.prototype // func 函數是 Function 構造函數的實例對象 console.log(func.__proto__.__proto__); // Object.prototype // func 函數的原型對象是 Object 構造函數的實例對象 console.log(func.__proto__.__proto__.proto__); // null // 這里就是原型鏈的頭了 , 所有原型鏈查到 Object.prototype 再往上就會返回 null /* 一般構造函數的原型鏈 */ function Obj(){ Func.prototype.name = "oswald"; } var obj = new Obj(); console.log(obj); // {} console.log(obj.name); // oswald // obj 對象通過原型鏈查找到了 name 屬性 console.log(Obj.__proto__); // Obj.prototype // obj 對象是 Obj 構造函數的實例對象 console.log(Obj.__proto__.__proto__); // Object.prototype // obj 對象的原型對象是 Object 構造函數的實例 console.log(Obj.__proto__.__proto__.__proto__); // null // 到頭了原型鏈繼承
原型鏈繼承的原理就是實例對象可以訪問原型對象的屬性和方法 , 并通過原型鏈向上查找
function Oswald(){ this.color = "red"; Oswald.prototype.sayName = function(){ console.log(this.name) }; } var oswald = new Oswald(); function Yin(name, age){ this.name = name; this.age = age; Yin.prototype.sayAge = function(){ console.log(this.age); } } Yin.prototype = oswald; /* 原型鏈繼承的核心 , 把父類型 ( Oswald ) 的實例對象 ( oswald ) 設置為子類型 ( Yin ) 的原型屬性 ( Yin.prototype ) */ var yin = new Yin("oswald", 24); // 必須要先繼承再創建實例 , 否則會出現 Yin.prototype != yin.__proto__ 的情況 yin.sayName(); // oswald 繼承了 Oswald 類型原型上的方法 yin.sayAge(); // 24 繼承了 Yin 類型原型上的方法借用構造函數式繼承
我們之前討論的原型鏈繼承 , 不能在創建子類型的實例對象的時候 , 給父類型的構造函數傳遞參數 , 如果要給父類型的構造函數傳遞參數 , 就會影響所有的子類型實例對象
如果我們想要解決這個問題 , 可以借調父類型的構造函數 , 在新創建的對象上執行構造函數
function Oswald(color){ this.color = color; this.sayName = function(){ console.log(this.name) }; } function Yin(name, age, color){ Oswald.call(this, color); // 在 Yin 構造函數創建的新對象中調用 Oswald 函數 this.name = name; this.age = age; } var yin = new Yin("yin", 24, "red"); yin.sayName(); // yin組合式繼承
但是借用構造函數繼承只能夠繼承父類型自己的屬性和方法 , 不能繼承原型鏈上 , 這個時候我們可以使用原型鏈和借用構造函數的組合式繼承 , 但是這個方法會調用兩次父類型構造函數
function Super(color){ this.color = color; // 自己的屬性 Super.prototype.sayName = function(){ console.log(this.name) }; // 原型鏈上的方法 } function Sub(name, age, color){ Super.call(this, color); // 第二次調用 Super , 被當做普通函數調用 // 繼承 Super 構造函數自己的屬性和方法 this.name = name; this.age = age; } Sub.prototype = new Super(); // 第一次調用 Super , 被當做構造函數調用 // 繼承 Super 原型鏈上的屬性和方法 var yin = new Sub("yin", 24, "red"); yin.sayName(); // yin原型式繼承
ES 5 中使用 Object.create( o ) 方法規范了原型式繼承 , 這個方法會返回一個新對象 , 新對象的原型對象指向傳入的參數對象 o
function obj(o){ // Object.create( ) 方法的原理 function F(){}; F.prototype = o; return new F(); } var person = { name: "oswald", color: ["red"] } var person1 = obj(person); var person2 = Object.create(person); console.log(person1 === person2); // false console.log(person1.__proto__ === person2.__proto__); // true寄生組合式繼承
目前最優的繼承模式
function Super(color){ this.color = color; Super.prototype.sayName = function(){ console.log(this.name); } } function Sub(name, color){ Super.call(this, color); // 借調 Super 構造函數繼承實例屬性 this.name = name; } var F = Object.create(Super.prototype); F.constructor = Sub; Sub.prototype = F; var yin = new Sub("oswald","red"); yin.sayName(); // oswald
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/108272.html
摘要:注本文內容來深入面向對象模式與實踐中節。面向對象設計與過程式編程面向對象設計和過程式編程有什么不同呢可能有些人認為最大的不同在于面向對象編程中包含對象。面向對象編程和過程式編程的一個核心區別是如何分配職責。 注:本文內容來中6.2節。 6.2 面向對象設計與過程式編程 ??面向對象設計和過程式編程有什么不同呢?可能有些人認為最大的不同在于面向對象編程中包含對象。事實上,這種說法不準確。...
面向對象設計是一類編程方式,此編程方式的落地式需要使用類和目標來達到,因此,面向對象設計本身就是對類和目標的應用,今日給大家介紹一下python面向對象設計開發設計及本質特征,感興趣的小伙伴一起了解一下吧 序言 面向對象設計對新手而言不難理解但無法運用,盡管我們給大家匯總過面向對象戰略部署方式(定義類、創建對象、給目標發信息),可是看似簡單其實不簡單。大量程序編寫訓練與閱讀高質量的編碼有可...
小編寫這篇文章的主要目的,主要是來給大家介紹關于Python的一些事情,主要還是涉及到面對面對象編程的一些實例,其中,主要涉及到的內容涵蓋封裝、繼承、多態等多種形式,就具體的形式,下面就給大家詳細解答下。 Python是一門面向對象的語言。面向對象都有三大特性:封裝、繼承、多態。 下面分別來說說這三大特性: 1、封裝 隱藏對象的屬性和實現細節,僅對外提供公共訪問方式。在python中用...
Python 是一種解釋型的、交互式的、面向對象的編程語言,它結合了非凡的功能和非常清晰的語法。Python Library Reference 記錄了內置的和標準的類型、常量、函數和模塊。語法格式:python [參數]常用參數:參數 描述-c 直接運行 python 語句-v 會輸出每一個模塊引用信息-i 運行完 python 腳本文件以后打開一個 python 環境-m 將模塊按照腳本執行命...
入坑 Python自從進入公司,到現在也有半年的時間。這半年的時間從 python 到入門到開發了幾個小項目,類型涵蓋了web應用 程序、爬蟲程序 (scrapy),python腳本工具,自動化工具。對 python 語言也越來越熟悉,當然也有所感悟和總結。首先 Python 真的讓語言成 了一個工具,入門代價很小,上手能夠開發出小工具,可以更快體驗到編程的樂趣。但是做到pythonic需要更多的...
閱讀 2662·2021-11-25 09:43
閱讀 2472·2021-09-22 15:29
閱讀 984·2021-09-22 15:17
閱讀 3628·2021-09-03 10:36
閱讀 2223·2019-08-30 13:54
閱讀 1740·2019-08-30 11:23
閱讀 1163·2019-08-29 16:58
閱讀 1290·2019-08-29 16:14