function createPerson(name, age, job) { var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function() { alert(this.name); } return 0; } var person1 = createPerson('Nicholas', 29, 'software engineer'); var person2 = createPerson('greg', 27, 'doctor')
function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = function () { alert(this.name); } return 0; } var person1 = new Person('Nicholas', 29, 'software engineer'); var person2 = new Person('greg', 27, 'doctor'); alert(person1.constructor == Person) // true
構造函數始終都應該以一個大寫之母開頭,而非構造函數則應該以小寫之母開頭。javascript
建立Person的新實例,必須使用new操做符。java
構造函數與普通函數的區別app
構造函數的缺點函數
從邏輯上講,能夠這樣this
function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = new Function('alert(this.name)'); //與聲明函數在邏輯上是等價的 } alert(person1.sayName == person2.sayName) // false
function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = sayName; } function sayName() { alert(this.name); } var person1 = new Person('Nicholas', 29, 'software engineer'); var person2 = new Person('greg', 27, 'doctor') // 咱們把sayName()定義在外部,person1 和person2 共享了在全局做用域中定義的同一個sayname()函數。 // 若是對象須要定義不少方法,那麼就要定義不少個全局函數,因而這個自定義的引用類型沒有分裝性可言 // 可使用原型模式
使用原型對象的好處是可讓全部對象實例共享它所包含的屬性和方法prototype
function Person() { } Person.prototype.name = 'nicholas'; Person.prototype.age = 29; Person.prototype.job = 'software engineer'; Person.prototype.sayName = function () { alert(this.name); } var person1 = new Person(); person1.sayName(); // nicholas var person2 = new Person(); person2.sayName(); // nicholas alert(person1.sayName == person2.sayName); // true // 什麼是原型對象 // 只要建立了一個函數,就會根據一組特定的規則爲該函數建立一個prototype屬性,這個屬性指向函數的原型對象。 // 在默認狀況下,全部的原型對象都會自動得到一個constructor(構造函數)屬性。這個屬性包含一個指向prototype屬性所在函數的指針。 // Person.prototype constructor指向Person. // 而經過這個構造函數,咱們能夠原型對象添加其餘屬相和方法。
function Person() { } Person.prototype = { name: 'nicholas', age: 29, job: 'software engineer', sayName: function() { alert(this.name); } } var friend = new Person();
原型鏈是做爲實現繼承的主要方法。指針
- 其基本思想就是利用原型讓一個引用類型繼承另外一個引用類型的屬性和方法、
function SuperType() { this.property = true; } SuperType.prototype.getSuperValue = function() { return this.property; }; function SubType() { this.subproperty =false; } // 繼承了supertype SubType.prototype = new SuperType(); SubType.prototype.getSubValue = function() { return this.subproperty; } var instance = new SubType(); alert(instance.getSuperValue()) //true
使用apply() 和call() 方法也能夠在未來新建立的對象上執行構造函數code
function SuperType() { this.colors = ['red', 'blue', 'green']; } function SubType() { // 繼承了 supertype SuperType.call(this); } var instance1 = new SubType(); instance1.colors.push('black'); alert(instance1.colors)// red blue green black var instance2 = new SubType(); alert(instance2.colors); // 'red', 'blue', 'green'
// 1.傳遞參數 function SuperType(name) { this.name = name; } function SubType() { // 繼承了SuperType同時還傳遞了參數 SuperType.call(this, 'nicholas'); // 實例屬性 this.age = 29; } var instance = new SubType(); alert(instance.name); alert(instance.age);
經過借用構造函數來實現對實例屬性的繼承。這樣,即經過在原型上定義方法實現了函數複用,有能保證每一個實例都有它本身的屬性、對象
function SuperType(name) { this.name = name; this.colors = ['red', 'blue', 'green']; } SuperType.prototype.sayName = function() { alert(this.name); } function SubType(name, age) { // 繼承屬性 SuperType.call(this, name); this.age = age; } // 繼承方法 SubType.prototype = new SuperType(); SubType.prototype.constructor = SubType; SubType.prototype.sayAge = function() { alert(this.age); } var instance1 = new SubType('nicholas', 29); instance1.colors.push('black'); alert(instance1.colors);//red,blue,green,black instance1.sayName()//nicholas instance1.sayAge()// 29 var instance2 = new SubType('greg', 27); alert(instance2.colors);//red,blue,green instance2.sayName()//greg instance2.sayAge()// 27