原型鍊
這裡隻是通過一些案例補充之前對原型,原型鍊,instanceof的細節。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// // 函數構造器
// console.log(Function); //ƒ Function() { [native code] }
// // 對象構造器
// console.log(Object); //ƒ Object() { [native code] }
// // 數組構造器
// console.log(Array); //ƒ Array() { [native code] }
// // 字元串構造器
// console.log(String); //ƒ String() { [native code] }
// // 數字構造器
// console.log(Number); //ƒ Number() { [native code] }
// // 布爾構造器
// console.log(Boolean); //ƒ Boolean() { [native code] }
// 定義一個函數(構造函數)Father
function Father() { }
// 使用構造函數建立對象father
var father = new Father()
// 使用字面量形式建立對象
var car = {}
// 使用Object構造器建立對象
var home = new Object()
// 使用字面量形式建立一個數組arr
var arr = [1, 2, 3]
/**
* prototype原型對象,即原型對象也是對象,是對象就可以通過原型鍊繼承其原型上的屬性和方法,
* prototype是對象,是以prototype也可通過原型鍊繼承其原型上的屬性和方法
*/
/**
* 每個對象都可以通過原型鍊通路(或者說繼承)其原型鍊上的屬性和方法
* 使用構造函數建立的對象,可以通過原型鍊繼承這個構造函數上的屬性和方法(說白了就是這個構造函數的原型)
* */
console.log(father.__proto__ === Father.prototype); //true
/**
* 這個構造函數的原型對象,即Father.prototype,也可通過原型鍊繼續繼承它(Father.prototype)原型鍊上的屬性和方法
*/
console.log(Father.prototype.__proto__); //true
console.log(Father.prototype.__proto__ === Object.prototype); //true
console.log(Father.prototype.constructor === Father); //true
// 通過構造函數建立的對象,可以通過原型鍊通路其原型
console.log(father.__proto__) //true
// 通過字面量形式建立的對象,其本身就繼承Object.prototype
console.log(car.__proto__.constructor === Object);
console.log(arr.__proto__ === Array.prototype); //true
// 同理,函數實際也是一個對象,是以,函數也可以通過其原型鍊通路其原型
console.log(Function.__proto__ === Function.prototype);//true
console.log(Function.__proto__ === Function.prototype);//true
console.log(Function);
console.log(Function.prototype); //ƒ () { [native code] }
/**
* 所有函數都有自己的prototype
*/
console.log(Object.prototype); //{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
console.log(Array.prototype); //[constructor: ƒ, concat: ƒ, copyWithin: ƒ, fill: ƒ, find: ƒ, …]
console.log(String.prototype); //String {"", constructor: ƒ, anchor: ƒ, big: ƒ, blink: ƒ, …}
console.log(Number.prototype); //Number {0, constructor: ƒ, toExponential: ƒ, toFixed: ƒ, toPrecision: ƒ, …}
console.log(Boolean.prototype); //Boolean {false, constructor: ƒ, toString: ƒ, valueOf: ƒ}
console.log(Array.prototype === Function.prototype); //false
console.log(String.prototype === Function.prototype); //false
console.log(Number.prototype === Function.prototype); //false
console.log(Object.__proto__ === Function.prototype); //true
console.log(Array.__proto__ === Function.prototype); //true
console.log(Function.__proto__ === Function.prototype);//true
console.log(String.__proto__ === Function.prototype); //true
console.log(Number.__proto__ === Function.prototype); //true
console.log(Boolean.__proto__ === Function.prototype); //true
/**
* Object.protype是原型鍊的頂端,它在往上就是null
* 其餘所有對象(Array,String,Number...)會通過原型鍊繼承Object.prototype
*/
console.log(Object.prototype
.__proto__
); //null
console.log(Array.prototype
.__proto__
); //{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
console.log(String.prototype
.__proto__
); //{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
console.log(Number.prototype
.__proto__
); //{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
console.log(Boolean.prototype
.__proto__
); //{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
console.log(Array.prototype.__proto__ === Object.prototype); //true
console.log(String.prototype.__proto__ === Object.prototype); //true
console.log(Number.prototype.__proto__ === Object.prototype); //true
console.log(Boolean.prototype.__proto__ === Object.prototype); //true
console.log(Array); //ƒ Array() { [native code] }
console.log(Array.prototype); //prototype是原型對象,對象就有__proto__。它還有constructor儲存本身,還有本身的屬性以及方法
console.log(Array.prototype.constructor === Array); //true
console.log(Array.__proto__ === Function.prototype); //true
console.log(Array.prototype.__proto__); //{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
console.log('--------------');
/**
* 所有對象都可以通過new建立,比如數組:new Array();對象:new Object();函數:new Function();字元串:new String()....
* new後面的叫構造函數,即Array();Object();Function();String()...都是構造函數
* 構造函數也是函數,那麼就有一個問題,js所有東西都是對象的話,是先有對象還是現有構造函數?(因為對象也是new出來的)
* 如果是先有函數,再通過函數new産生的對象,那麼函數又是怎麼來的?是以就類似:先有雞還是現有雞蛋的問題。
* 是以,函數是怎麼來的?這個解釋了就說的通了
* */
/**
* 函數有prototype,對象有__proto__
* 函數可以通過prototype.constructor通路自己構造它的函數
* 對象可以通過__proto__繼承上層的prototype
*/
console.log(Function instanceof Object); //true
// 函數就有prototype
console.log(Function.prototype instanceof Object); //true
console.log(Function.prototype.__proto__ instanceof Object); //fasle
// 函數也是一個對象,對象就有__proto__,是以函數有__proto__
console.log(Function.__proto__ instanceof Object); //true
console.log(Function.__proto__ instanceof Object); //true
console.log(Function.__proto__.__proto__ instanceof Object); //false
console.log(Function.__proto__.__proto__ instanceof Object); //false
console.log(Function.constructor === Function); //true
console.log('-----------------------');
var cat = {}
function Dog() { }
var dog = new Dog()
console.log(cat.__proto__ === Function.prototype); //false
console.log(dog.__proto__ === Function.prototype); //false
console.log(cat.__proto__ === Object.prototype); //true
console.log(dog.__proto__ === Object.prototype); //false
console.log(cat.__proto__ === dog.__proto__); //false
console.log(dog.__proto__ === Dog.prototype); //true
</script>
</body>
</html>
複制
圖解
這裡引用網上的圖,個人也認為這張圖很具體很全面。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIwIjNx8CX39CXy8CXycXZpZVZnFWbp9zZlBnauUzN4YjZ0ImN3UGZxYGM1gDOzAzM3ETMyQmNwQmMjVzNvw1NykjN0cDOtUGall3LcVmdhNXLwRHdo9CXt92YucWbpRWdvx2Yx5yazF2Lc9CX6MHc0RHaiojIsJye.jpeg)