JS 面向對象之原型鏈
對象的原型鏈
- 只要是對象就有原型
- 原型也是對象
- 只要是對象就有原型, 並且原型也是對象, 因此只要定義了一個對象, 那么就可以找到他的原型, 如此反復, 就可以構成一個對象的序列, 這個結構就被成為原型鏈
- 原型鏈到哪里是一個頭?
- 一個默認的原型鏈結構是什么樣子的?
- 原型鏈結構對已知語法結構有什么修正?
原型鏈的結構
- 原型鏈繼承就是利用就是修改原型鏈結構( 增加、刪除、修改節點中的成員 ), 從而讓實例對象可以使用整個原型鏈中的所有成員( 屬性和方法 )
- 使用原型鏈繼承必須滿足屬性搜索原則
屬性搜索原則
- 所謂的屬性搜索原則, 就是對象在訪問屬性與方法的時候, 首先在當前對象中查找
- 如果當前對象中存儲在屬性或方法, 停止查找, 直接使用該屬性與方法
- 如果對象沒有改成員, 那么再其原型對象中查找
- 如果原型對象含有該成員, 那么停止查找, 直接使用
- 如果原型還沒有, 就到原型的原型中查找
- 如此往復, 直到直到 Object.prototype 還沒有, 那么就返回 undefind.
- 如果是調用方法就包錯, 該 xxxx 不是一個函數
原型鏈結構圖
- 構造函數 對象原型鏈結構圖
function Person (){};
var p = new Person();

-
{} 對象原型鏈結構圖

-
[] 數組原型鏈結構圖

-
Object.prototype對應的構造函數

-
div 對應的構造函數
-
div -> DivTag.prototype( 就是 o ) -> Object.prototype -> null
var o = {
appendTo: function ( dom ) {
}
};
function DivTag() {}
DivTag.prototype = o;
var div = new DivTag();

函數的構造函數 Function
在 js 中 使用 Function 可以實例化函數對象. 也就是說在 js 中函數與普通對象一樣, 也是一個對象類型( 非常特殊 )
- 函數是對象, 就可以使用對象的動態特性
- 函數是對象, 就有構造函數創建函數
- 函數是函數, 可以創建其他對象(函數的構造函數也是函數)
- 函數是唯一可以限定變量作用域的結構

函數是 Function 的實例
new Function( arg0, arg1, arg2, ..., argN, body );
- Function 中的參數全部是字符串
- 該構造函數的作用是將 參數鏈接起來組成函數
- 如果參數只有一個, 那么表示函數體
- 如果參數有多個, 那么最后一個參數表示新函數體, 前面的所有參數表示新函數的參數
- 如果沒有參數, 表示創建一個空函數
創建一個打印一句話的函數
// 傳統的
function foo () {
console.log( '你好' );
}
// Function
var func = new Function( 'console.log( "你好" );' );
// 功能上, 這里 foo 與 func 等價
創建一個空函數
// 傳統
function foo () {}
// Function
var func = new Function();
傳入函數內一個數字, 打印該數字
// 傳統
function foo ( num ) {
console.log( num );
}
// Function
var func = new Function ( "num" ,"console.log( num );" );
func();
利用 Function 創建一個函數, 要求傳入兩個數字, 打印其和
var func = new Function( 'num1', 'num2', 'console.log( num1 + num2 );' );
練習: 利用 Function 創建一個函數, 要求允許函數調用時傳入任意個數參數, 並且函數返回這些數字中最大的數字.
練習: 利用 Function 創建一個求三個數中最大數的函數.
// 傳統
function foo ( a, b, c ) {
var res = a > b ? a : b;
res = res > c ? res : c;
return res;
}
// Function
var func = new Function( 'a', 'b', 'c', 'var res = a > b ? a : b;res = res > c ? res : c;return res;' )
解決代碼太長的辦法:
- 利用 加法 連接字符串
var func = new Function( 'a', 'b', 'c',
'var res = a > b ? a : b;' +
'res = res > c ? res : c;' +
'return res;' );
- 利用字符串特性( 剛學 )
function foo ( a, b, c ) {
var res = a > b ? a : b;
res = res > c ? res : c;
return res;
}
var func = new Function( 'a', 'b', 'c', 'return foo( a, b, c );' );
- ES6 的語法( 少瀏覽器實現 )
- 使用 鍵盤左上角的 左單引號 表示可換行字符串的界定符
- (最終)利用 DOM 的特性完成該方法
arguments 對象
arguments 是一個偽數組對象. 它表示在函數調用的過程中傳入的所有參數的集合.
在函數調用過程中沒有規定參數的個數與類型, 因此函數調用就具有靈活的特性, 那么為了方便使用,
在 每一個函數調用的過程中, 函數代碼體內有一個默認的對象 arguments, 它存儲着實際傳入的所有參數.
js 中函數並沒有規定必須如何傳參
- 定義函數的時候不寫參數, 一樣可以調用時傳遞參數
- 定義的時候寫了參數, 調用的時候可以不傳參
- 定義的時候寫了一參數, 調用的時候可以隨意的傳遞多個而參數
在代碼設計中, 如果需要函數帶有任意個參數的時候, 一般就不帶任何參數, 所有的 參數利用 arguments 來獲取.
一般的函數定義語法, 可以寫成:
function foo ( /* ... */ ) {
}
利用 Function 創建一個函數, 要求允許函數調用時傳入任意個數參數, 並且函數返回這些數字中最大的數字.
function foo ( ) {
// 所有的參數都在 arguments 中. 將其當做數組使用
// 問題而已轉換成在有一個數組中求最大值
var args = arguments;
var max = args[ 0 ];
for ( var i = 1; i < args.length; i++ ) {
if ( max < args[ i ] ) {
max = args[ i ];
}
}
return max;
}
練習: 利用 Function 寫一個函數, 要求傳入任意個數字 求和
函數的原型鏈結構
任意的一個函數, 都是相當於 Function 的實例. 類似於 {} 與 new Object() 的關系
function foo () {};
// 告訴解釋器, 有一個對象叫 foo, 它是一個函數
// 相當於 new Function() 得到一個 函數對象
- 函數有
__proto__屬性 - 函數的構造函數是 Function
- 函數應該繼承自
Function.prototype Fucntion.prototype繼承自Object.protoype- 構造函數有prototype, 實例對象才有__proto__指向原型, 構造函數的原型才有 constructor 指向構造函數
intanceof
array instanceof Array
判斷 構造函數 Array 的原型 是否在 實例對象 array 的原型鏈存在
