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);