JavaScript基礎 —— 原型&&原型鏈
建構函式
function Foo(name, age) {
this.name = name;
this.age = age;
this.class = 'class-1';
//return this ; //預設有這一行
}
var f = new Foo('張三', 22);
var f1 = new Foo('李四', 29);
建構函式 - 擴充套件
var a={} 其實是 var a=new Object() 的語法糖
var a=[] 其實是 var a=new Array() 的語法糖
function Foo() {....} 其實是 var Foo=new Function(...)
使用 instanceof 判斷一個函式是否是一個變數的建構函式
原型規則和示例
- 所有的引用型別(陣列、物件、函式),都具有物件屬性(即可自有擴充套件的屬性),
null
除外
- 所有的引用型別(陣列、物件、函式),都有一個
__proto__
屬性(隱式原型),屬性值是一個普通的物件
var obj = { };
obj.x=100;
console.log(obj.__proto__);
// {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
var arr = [];
arr.x = 200;
console.log(arr.__proto__);
// [constructor: ƒ, concat: ƒ, find: ƒ, findIndex: ƒ, pop: ƒ, …]
function fn() {};
fn.x = 300;
console.log(fn.__proto__);
// ƒ () { [native code] }
var d = null;
console.log(d.__proto__);
// Uncaught TypeError: Cannot read property '__proto__' of null
- 所有的
函式
,都有一個 prototype
屬性(顯式原型),屬性值也是一個普通物件
console.log(fn.prototype);
// {constructor: ƒ}
- 所有的引用型別(陣列、物件、函式),
__proto__
屬性值指向它的建構函式的 prototype
屬性值
console.log(obj.__proto__ === Object.prototype);
// true
- 當檢視得到一個物件(所有的引用型別)的某個屬性時,如果這個物件本身沒有這個屬性,那麼會去它的
__proto__
(即它的建構函式的 prototype
)中尋找。
// 建構函式
function Foo(name, age) {
this.name = name;
}
Foo.prototype.alertName = function() {
console.log('alertName' + this.name);
}
// 建立示例
var f = new Foo('張三');
f.prientname = function() {
console.log('prientname' + this.name);
}
// 測試
f.prientname(); // prientname張三
f.alertName(); // alertName張三
原型鏈
// 建構函式
function Foo(name, age) {
this.name = name;
}
Foo.prototype.alertName = function() {
console.log('alertName' + this.name);
}
// 建立示例
var f = new Foo('張三');
f.prientname = function() {
console.log('prientname' + this.name);
}
// 測試
f.prientname(); // prientname張三
f.alertName(); // alertName張三
f.toString(); // "[object Object]" 在f.__proto__.__proto__中查詢,即Object的顯式原型中尋找
instanceof
-
instanceof
用於判斷 引用型別
屬於哪個 建構函式
的方法
// f的 __proto__ 一層一層網上找,找到對應的 Foo.prototype
f instanceof Foo //true
f instanceof Object //true
q:如何準確判斷一個變數是陣列型別
var arr=[]
// 可以正確判斷的情況
arr instanceof Array //true
Object.prototype.toString.call(arr) // "[object Array]"
Object.prototype.toString.apply(arr) // "[object Array]"
Array.isArray(arr) // true
// 不能判斷的情況
typeof arr // object 是無法判斷是否是陣列的
// 不準確
arr.constructor === Array //true 但是原型鏈可以被改寫,這樣判斷不安全
// 擴充套件 相容老版本瀏覽器,isArray的寫法
if(!Array.isArray){
Array.isArray = function(arg){
return Object.property.toString.call(arg) === '[object Array]'
}
}
q:寫一個原型鏈繼承的例子
function Elem(id) {
this.elem = document.getElementById(id);
}
Elem.prototype.html = function(val) {
var elem = this.elem;
if (val) {
elem.innerHTML = val;
return this; // 後續的鏈式操作
} else {
return elem.innerHTML;
}
}
Elem.prototype.on = function(type, fn) {
var elem = this.elem;
elem.addEventListener(type, fn);
return this;
}
var main = new Elem('main')
main.html('<p>Hello World</p>').on('click', function() {
alert('Hello javascript')
})
q:描述 new
一個物件的過程
- 建立一個物件
-
this
指向這個新物件
- 執行程式碼,即對
this
賦值
- 返回
this
function Foo(name, age) {
this.name = name;
this.age = age;
this.class = 'class-1';
//return this ; //預設有這一行
}
var f = new Foo('張三', 22);
var f1 = new Foo('李四', 29);