1. 程式人生 > >這樣理解原型,更加容易易懂

這樣理解原型,更加容易易懂

== ciw iic 驗證 函數的原型 存在 cif swd 枚舉

無論什麽時候,只要創建了一個新函數,就會根據一組特定的規則為該函數創建一個prototype屬性,這個屬性指向函數的原型對象。所有原型對象都會自動獲得一個consturctor屬性,這個屬性指向prototype屬性所在函數的指針。Person.prototype.constructor 指向Person。通過這個構造函數可以繼續為原型對象添加其他屬性和方法.

1.prototype:

只要我們定義一個函數,prototype作為函數的屬性存在了,它的初始值是一個對象。

function Person () {

}
Person.prototype

技術分享

2.給對象添加屬性和方法

給通過構造函數創建的對象添加屬性和方法:在函數內部通過this

給構造函數返回的對象添加屬性。

function Person (name, age) {
    this.name = name;
    this.age = age;
}
var person1 = new Person();

通過構造函數的prototype屬性給對象添加屬性和方法,這種方式添加的屬性和方法會被所有的對象實例共享。

function Person (name, age) {
    this.name = name;
    this.age = age;
}
Person.prototype.sayName = function() {
    return this.name;
}
Person.prototype.breathes = ‘空氣‘;
var person1 = new Person(‘張三‘, 20);
var person2 = new Person(‘李四‘, ‘21‘);
person1.sayName();

註意:一定要前在原型中定義方法和屬性,然後再使用:

person2.eat();
Person.prototype.eat = function() {
    console.log(‘吃飯啦‘);
}

技術分享

註意:原型對象中屬性和對象自己的屬性是有區別的,對象自己屬性默認是可配置可枚舉的,而我們在原型中添加的屬性是不可配置的,但確是可枚舉。

function Person (name, age) {
      this.name = name;
      this.age = age;
    }
    Person.prototype.sayName = function() {
        return this.name;
    }
    Person.prototype.breathes = ‘空氣‘;

    var person1 = new Person(‘張三‘, 20);

    delete person1.sayName;

    console.log(person1.sayName())   // ‘張三‘

    for(propName in person1){
      console.log(propName)       // name age sayName breathes
    }

3.覆蓋原型中屬性

如果對象出現了和原型對象中同名的屬性或方法,原型的屬性和方法會被覆蓋掉。這是因為,我們在訪問對象的屬性或方法時,優先在對象自己的屬性列表中查找,如果找到的話,就使用自己的屬性,如果找不到的,就去原型對象中查找。

在下面的示例中,原型對象中sayName方法被對象自己的sayName方法遮擋住了,所以最終調用的是對象自己的sayName方法。

function Person (name, age) {
    this.name = name;
    this.age = age;
}
Person.prototype.sayName = function() {
    return this.name;
}

var person1 = new Person(‘李四‘, 20);
person1.sayName = function() {
    console.log(‘對象自己的sayName方法‘)
}
person1.sayName();      // ‘對象自己的sayName方法‘

4.hasOwnProperty()方法和in操作符的區別

判斷對象中是否存在某個屬性,除了使用in操作符,還可以使用hasOwnProperty()方法。hasOwnProperty()方法只在對象自己的屬性列表中搜索;而in操作符,先在對象自己的屬性列表中查找,如果找不到,接著去原型對象的屬性列表中查找。

function Person (myname, myage) {
  this.name = myname;
  this.age = myage;

}
Person.prototype.sayName = function() {
  console.log(this.name)
}
var person1 = new Person(‘小明‘, 18, ‘女‘);
// 使用hasOwnProperty()方法
console.log(person1.hasOwnProperty(‘name‘))     // ture
console.log(person1.hasOwnProperty(‘sayName‘))  // false
// 使用in操作符
console.log(‘sayName‘ in person1)               // true

5.isPrototypeOf()方法

該方法是用來判斷一個對象是否是另一個對象的原型。例如:

var monkey = {
    feeds: ‘香蕉‘,
    breathes: ‘空氣‘
}

function Human (name) {
    this.name = name;
}

Human.prototype = monkey;
接下來我們來判斷monkey對象是否是Human原型:

var person1 = new Human(‘李四‘);
monkey.isPrototypeOf(person1)
驗證person1的原型是否是monkey

console.log(Object.getPrototypeOf(person1))
console.log(Object.getPrototypeOf(person1) === monkey)

6.proto

我們先前講過,當我們訪問一個當前對象中沒有的屬性時,會去prototype對象中查找。

var developer = new Human(‘李四‘);
developer.feeds = ‘大米飯‘;
developer.hacks = ‘JavaScript‘;

developer.hacks     // ‘JavaScript‘

當我們訪問developer對象中不存在的breathes屬性時,就會去原型對象中查找,仿佛有一個神秘的鏈接指向原型對象。

developer.breathes;  // ‘air‘

在大多數瀏覽器中都是以__proto__屬性作為這個神秘的鏈接

console.log(developer.__proto__ === monkey);  // true

在學習的過程中,我們可以使用這個鏈接,但是在實際的項目開發中不要使用它,因為並不是所有的瀏覽器都有__proto__屬性。

我們可以使用Object.getPrototypeOf()代替它。

7.擴展(增強)內置的構造函數創建的對象

內置的構造函數有ArrayStringObjectFunction等,我們可以通過改變原型對象的方式增強由這些構造函數創建的對象。

例如,給數組添加一個inArray()方法,用於判斷數組中是否包含某個元素:

Array.prototype.inArray = function (ele) {
for (var i = 0; i < this.length; i++) {
  if(this[i] === ele) {
    return true;
  }
}
return false;
};
var colors = [‘red‘, ‘green‘, ‘blue‘];
console.log(colors.inArray(‘red‘));        // true
console.log(colors.inArray(‘purple‘));     // false

這樣理解原型,更加容易易懂