原型鏈


原型和實例對象

每一個函數天生都有一個原型(prototype),當函數被new關鍵字調用的時候,產生的實例的__proto__都指向次構造函數的prototype對象

 

 

 

 function Person() {}
 console.log(Person.prototype);

  function Person() {}
      var xiaoming = new Person();
      console.log(xiaoming);

 

此時我們可以判斷一下這個xiaoming的__proto__是否等於Person構造函數的prototype

 console.log(xiaoming.__proto__ == Person.prototype)

構造函數的prototype指向了誰,該實例的__proto__就指向誰

__proto__有什么用?

所有的對象都有__proto__屬性,這個屬性指向的就是自己的“原型對象”,每一個對象在通過點語法訪問自己的屬性、方法的時候,都擁有原型鏈查找(proto search)的功能。什么叫做原型鏈查找?如果當前對

象自己身上有這個屬性或者方法,則用自己的,如果沒有則沿着__proto__指向的原型對象中去查找,如果在原型對象上有這個方法,則調用這個原型對象屬性或者方法

 function Person(name,sex) {
        this.name = name;
        this.sex = sex;
      }
      Person.prototype.sayHello = function () {
        console.log("你好,我是" + this.name + ",我是一個" + this.sex + "生,")
      };
      var xiaoming = new Person("小明",  "");
      var xiaohong = new Person("小紅", "");
      console.log(xiaoming);
      console.log(xiaohong);

此時就可以看到方法是在原型對象上(也就是構造函數的原型上)

 

 

此時我們也可以驗證xiaoming和xiaohong調用的是同一個函數

      console.log(xiaoming.sayHello == xiaohong.sayHello)     

 

 語法:

function 構造函數(屬性1,屬性2,屬性3) {
this.屬性1 = 屬性1;
this.屬性2 = 屬性2;
this.屬性3 = 屬性3;
}
構造函數.prototype.方法1 = function(){

}
構造函數.prototype.方法2 = function(){

}

構造函數.prototype.方法3 = function(){

}

 

內置構造函數

在JavaScript中,對象是對象,數組是對象,函數是對象,正則表達式是對象。所有的引用類型值在JavaScript中都是對象。他們都有__proto__屬性

 

函數是可以通過new 關鍵字創建的,但是其他的數據類似也是可以通過關鍵字創建的

此時有一些內置構造函數和包裝類

new Array()、new Object()、new String()、new Nubmer()

 

引用類型值的構造函數

1、Object類型

任何的“真”對象都可以認為被Object new出來的

var obj = new Object();
obj.name = "小明";
obj.age = 20;
obj.sex = "";
//等同於
var obj = {
    name: '小明',
    age: 20,
    sex: ''
}

2、Function類型

Function是一個內置的構造函數,任何的函數都可以視作為是Function new出來的

var sum = new Function('a', 'b', 'return a + b;')
//等價於
var sum = function(a,b){
    return a + b
}

需要注意的是,這個是內置的構造函數,Function首字母是大寫的

3、Array類型

Array是一個內置的構造函數,任何的函數都可以視作為是Array new出來的

var arr = new Array(4);
arr[0] = 0;
arr[1] = 1;
arr[2] = 2;
arr[3] = 3;
console.log(arr)
//等價於
var arr = [0,1,2,3]

3、RegExp類型

RegExp是一個內置的構造函數,任何的函數都可以視作為是RegExp new出來的

var reg = new RegExp("\d", "g");
//等價於
var reg = /\d/g;

 4、基本類型值的包裝類

基本類型值三種:Number、String、Boolean

基本類型值也有構造器,他們被視作為“包裝類”。JavaScript為了體系的完整,所以就認為的造出了基本類型的包裝類,本質上沒有用

比如new一個Number

 var a = new Number(3);
 console.log(a);

[[PrimitiveValue]]對象叫做(原始值)作用就是賦值一個初始值,值是3

console.log(typeof a)

此時你會發現返回的是一個object,並不是一個number類型,但是一旦參與了運算,就變成了number類型,這種類叫做包裝類

var a = new Number(3);
console.log(typeof a);
a += 5;
console.log(typeof a);

 

 

 

String類型也是包裝類

var str = new String("hello");
console.log(str);

Boolean類型也是包裝類

   var boo = new Boolean(true);
      console.log(boo);

這些包裝類有一個隱式轉換功能

比如我們字符串的”100”,通過Number轉換后為100數字類型

   var a = new Number("100");
      console.log(a);

 

 

 

Number需要注意的是如果隱式轉換不是純數字不會和parseInt一樣凈化,會返回NaN

console.log(Number("100你好,我是"));
console.log(parseInt("100你好,我是"));

 

 

 

Object.prototype是所有原型鏈的終點

任何對象都有原型對象__proto__

更恐怖的是構造函數的實例的__proto__也是一個對象,這個對象也有__proto__

Object.prototype是所有原型鏈的終點,Object.prototype雖然也是一個對象,但是這個對象沒有__proto__指向的是空

 

 

 

看一個小案例

var obj = {};
console.log(obj.__proto__ == Object.prototype); 

Object是一個內置的構造函數,所有的對象都可以認為是Object new出來

  var obj = new Object();
      obj.age = 12;
      obj.name = "小明";
      console.log(obj);

 

 

 

此時需要注意這個對象必須是“真對象”,(而不是函數、正則表達式、數組的__proto__)的__proto__都是Object.prototype,因為它們本質上都是被Object new出來的

此時再看之前的Person構造函數就得到一個完整的原型鏈

 

內置構造函數的關系

規律:

  • 任何的“真”對象都是Object new出來的。所以只要是“真”對象,並且沒有特別的構造函數,它的__proto__就指向的是Object.prototype
  • 任何的函數都是Function new出來的,所以只要它是函數(內置構造函數也是函數),它的__proto__就會指向Function.prototype

 

 

 

      console.log(Object.__proto__ === Function.prototype);
      console.log(Array.__proto__ === Function.prototype);
      console.log(Number.__proto__ === Function.prototype);
      console.log(Number.__proto__.__proto__ === Object.prototype);
      console.log(Function.prototype == Function.__proto__);

比如數組字面量的原型鏈關系

 

原型鏈相關的方法

1、hasOwnProperty()方法

hasOwnProperty方法的作用是用來檢測某個屬性或者是方法是否在自己的身上

需要注意的是hasOwnProperty方法檢測的是該屬性是否真實的在自己的身上,而不是在原型鏈上面

 function Person(name) {
        this.name = name;
      }
      Person.prototype.sayHello = function () {
        alert("你好,我是" + this.name);
      };
      var xiaoming = new Person("小明");
      console.log(xiaoming.hasOwnProperty("name"));
      console.log(xiaoming.hasOwnProperty("sayHello"));

 

 

2、in運算符

in運算符返回的也是一個布爾值,作用是檢測某個對象有沒有能力調用該屬性或者是方法,不管這個屬性或者方法是否在原型鏈上,只看調用能力

語法:

字符串 in 對象
  function Person(name) {
        this.name = name;
      }
      Person.prototype.sayHello = function () {
        alert("你好,我是" + this.name);
      };
      var xiaoming = new Person("小明");
      console.log("name" in xiaoming); 
      console.log("sayHello" in xiaoming); 

 

 

3、 instanceof運算符

instanceof運算符返回的是一個布爾值,作用是用來檢測某一個對象是不是某一個函數的實例

原理是:o instanceof F,如果o在原型鏈上,返回的就是true,否則返回false

  function Person(name) {
        this.name = name;
      }
      Person.prototype.sayHello = function () {
        alert("你好,我是" + this.name);
      };

      function Dog() {}
      var xiaoming = new Person("小明");
      console.log(xiaoming instanceof Person); 
      console.log(xiaoming instanceof Object); 
      console.log(xiaoming instanceof Dog);

 

 

 

因為Person的prototype在xiaoming的原型鏈上,所以,xiaoming instanceof Person 返回的就是true,又因為Object的prototype也在小明的原型鏈上,所以xiaoming instanceof Object 返回的也是true,但是Dog

就和小明沒有關系了,所以返回false

 

再看下一個小題目

console.log(Object instanceof Object)
console.log(Function instanceof Function)
console.log(Number instanceof Number)
console.log(Function instanceof Object)

此時我們會發現Number instanceof Number 返回的是false

 

 

 

發現Number 的原型鏈上根本沒有Number什么事,本質上和Function和Object產生的關系,所以

console.log(Number instanceof Function)
console.log(Number instanceof Object)

 

 

發現Object.prototype是所有的對象原型鏈終點,所以 任何元素 instanceof Object 都是true

x instanceof Object // true

我們也發現了內置構造 instanceof 自己是false,但是由於Function是自己new自己,所以返回的是true

Function instanceof Function   //true

4、constructor屬性

任何一個prototype對象天生都有一個constructor屬性,指向的是對應的構造器

function Person(name) {
        this.name = name;
      }
      var xiaoming = new Person("xiaoming");
      console.log(Person.prototype.constructor);
      console.log(Person.prototype.constructor == Person);

 

 

可以驗證一下,constructor屬性是否在prototype上面

   function Person(name) {
        this.name = name;
      }
      var xiaoming = new Person("xiaoming");
      console.log(Person.prototype.hasOwnProperty("constructor")); 
      console.log(Person.hasOwnProperty("constructor"));

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM