每個對象都是基於引用類型建立的, 也能夠是開發人員本身建立的數組
工廠模式
let Person = {
name: 'agan',
age: 30,
job: 'it',
sayName: function() {
console.log(this.name)
}
}
複製代碼
這種模式抽象了建立具體函數的過程, 用函數來封裝以特定接口建立對象的細節函數
function createPerson(name, age, job) {
let o = new Object()
o.name = name
o.age = age
o.job = job
o.sayName = function() {
console.log(this.name)
}
return o
}
let p1 = createPerson('agan1', 30, 'it')
let p2 = createPerson('agan2', 40, 'cs')
複製代碼
函數 createPerson
接受三個參數來構建一個對象, 該函數能夠屢次調用. 工廠模式雖然解決了建立多個類似對象的問題, 卻沒有解決對象識別的問題(即怎樣知道一個對象的類型)ui
構造函數能夠用來建立特定類型的對象, 咱們能夠建立自定義的構造函數, 從而能夠定義自定義對象類型的屬性和方法this
function Person(name, age, job) {
this.name = name
this.age = age
this.job = job
this.sayName = function() {
console.log(this.name)
}
}
let p1 = new Person('agan1', 30, 'it')
let p2 = new Person('agan2', 40, 'cs')
複製代碼
Person
與 createPerson
不一樣:spa
this
return
語句p1
和 p2
保存着 Person
的兩個不一樣實例, 但都有一個 constructor
(構造函數) 屬性, 指向 Person
prototype
console(p1.constructor == Person); //true
console(p2.constructor == Person); //true
複製代碼
constructor
是用來表示對象類型的, instanceof
檢測對象類型更靠譜指針
alert(person1 instanceof Object); //true
alert(person1 instanceof Person); //true
alert(person2 instanceof Object); //true
alert(person2 instanceof Person); //true
複製代碼
var p1=new Person();
code
_p1
this
,將this指向該實例(_p1)a、若是函數沒有返回值(沒有return語句),那麼就會返回構造函數的實例(p1)對象
b、若是函數返回了一個基本數據類型的值,那麼本次構造函數的返回值是該實例(_p1)接口
function fn(){}
var f1 = new fn(); //f1就是fn的實例
function fn2(){
return "abc";
}
var f2 = new fn2(); //f2是fn2構造函數的實例
複製代碼
c、若是函數返回了一個複雜數據類型的值, 那麼本次函數的返回值就是該值
function fn3(){
return [1,3,5];
//數組是一個對象類型的值,
//因此數組是一個複雜數據類型的值
//-->本次構造函數的真正返回值就是該數組
//-->再也不是fn3構造函數的實例
}
var f3 = new fn3(); //f3仍是fn3的實例嗎?錯
//f3值爲[1,3,5]
複製代碼
new
調用new
調用就是普通函數// 看成構造函數
let person = new Person("agan", 29, "se");
person.sayName() // 'agan'
// 做爲普通函數調用
Person("agan1", 27, "IT"); // 添加到 window
window.sayName(); // "agan1"
// 在另外一個對象的做用域中調用
var o = new Object();
Person.call(o, "agan3", 25, "Nurse")
o.sayName(); // "agan3"
複製代碼
就是每一個方法都要在每一個實例上從新建立一遍,
sayName
指向不一樣的地址
person1.sayName === person2.sayName // true
複製代碼
能夠將 sayName 方法轉移到構造函數外部解決這個問題
function Person(name, age, job) {
this.name = name
this.age = age
this.job = job
this.sayName = sayName
}
function sayName() {
console.log(this.name)
}
let person1 = new Person("agan1", 29, "se");
let person2 = new Person("agan2", 27, "it");
person1.sayName === person2.sayName // true
複製代碼
上面代碼中將 sayName
函數轉移到了構造函數的外部, 在函數內部咱們將 sayName
指向這個全局函數, 這樣就解決了多個函數作一件事情的問題, 但又帶來了兩個新的問題:
咱們建立的每個函數都有一個
prototype
屬性, 這是一個指針, 指向了一個對象, 這個對象包含了特定類型對象的全部公共屬性和方法, 至關於一個父類
function Person() {
}
Person.prototype.name = 'agan'
Person.prototype.age = '30'
Person.prototype.job = 'it'
Person.prototype.sayName = function() {
console.log(this.name)
}
let p1 = new Person()
let p2 = new Person()
p1.sayName() // 'agan'
p2.sayName() // 'agan'
console.log(p1.sayName === p2.sayName) // true
複製代碼
上述代碼中 person1
和 person2
訪問的是同一組對象和方法 假如咱們想在全部的實例中共享一個數據, 那麼咱們可使用原型模式, 但是通常實例都有本身的屬性
構造函數用於建立實例屬性, 原型模式用於定義方法和共享的屬性
function Person(name, age, job) {
this.name = name
this.age = age
this.job = job
this.friends = ['a', 'b']
}
Person.prototype = {
constructor: Person,
sayName: function() {
console.log(this.name)
}
}
var p1 = new Person('agan', 29, 'it')
var p2 = new Person('agan2', 30, 'cs')
p1.friends.push('c')
console.log(p1.friends) // 'a' 'b' 'c'
console.log(p2.friends) // 'a' 'b'
console.log(p1.friends === p2.friends) // false
console.log(p1.sayName === p2.sayName) // true
複製代碼
在上面的代碼中, 實例屬性是定義在構造函數中的, 實例共享的屬性和方法是在原型中定義的
動態原型模式將全部信息都封裝在了構造函數中, 在構造函數中初始化原型
function Person(name, age, job) {
this.name = name
this.age = age
this.job = job
// 方法
if (typeof this.sayName !== 'function') {
Person.prototype.sayName = function() {
console.log(this.name)
}
}
}
let f = new Person('agan', 30, 'it')
f.sayName()
複製代碼
上述代碼中, sayName方法只有在不存在的狀況下, 纔會添加到原型中, 這段代碼只會在初次調用構造函數時纔會執行
基本思想: 建立一個函數, 該函數用來封裝建立對象的代碼, 而後再返回建立的對象 跟工廠模式相似
function Person(name, age, job) {
let o = new Object()
o.name = name
o.age = age
o.job = job
o.sayName = function() {
console.log(this.name)
}
return o
}
let f = new Person('agan', 20, 'it')
f.sayName() // 'agan'
複製代碼
穩妥對象: 指的是沒有公共屬性, 其方法也不引用
this
對象
this
new
操做符調用構造函數function Person(name, age, job) {
let o = new Object()
// 定義私有變量和函數
let name = name
let age = age
let job = job
// 添加方法
o.sayName = function() {
console.log(name)
}
return o
}
複製代碼
這種模式中建立的對象, 除了使用 sayName
方法外沒有其餘方法訪問name的值
let f = Person('agan', 30, 'it')
f.sayName() // agan
複製代碼