您好,登錄后才能下訂單哦!
function Foo(name, age){
this.name = name;
this.age = age;
this.class = 'class-1';
}
var f =new Foo('zhangsan',20);
命名規(guī)則:大寫字母開頭;
那么,在使用new操作符來調(diào)用一個構(gòu)造函數(shù)的時候,發(fā)生了什么呢?其實很簡單,就發(fā)生了四件事:
var obj ={};
obj.__proto__ = Foo.prototype;
Foo.call(obj);
return obj;
第一行,創(chuàng)建一個空對象obj。
第二行,將這個空對象的proto成員指向了構(gòu)造函數(shù)對象的prototype成員對象,這是最關(guān)鍵的一步,將新生成的對象的prop屬性賦值為構(gòu)造函數(shù)的prototype屬性,使得通過構(gòu)造函數(shù)創(chuàng)建的所有對象可以共享相同的原型。
第三行,將構(gòu)造函數(shù)的作用域賦給新對象,因此Foo函數(shù)中的this指向新對象obj,然后再調(diào)用Foo函數(shù)。于是我們就給obj對象賦值了。
第四行,返回新對象obj。
var a = {} 其實是 var a = new Object()的語法糖;
var a = [] 其實是 var a = new Array() 的語法糖;
function Foo(){...} 其實是 var Foo = new Function(...)
》所有引用類型都有構(gòu)造函數(shù)
》在實際開發(fā)過程中依然推薦使用左側(cè)的實現(xiàn)方式,易讀性、性能方面左側(cè)都更好;
① 原型規(guī)則
? 所有除了“null”以外的引用類型(數(shù)組、對象、函數(shù)),都具有對象特性,既可自由擴展屬性
? 所有除了“null”以外的引用類型(數(shù)組、對象、函數(shù)),都有一個proto 屬性(稱它為‘隱式原型’,proto翻譯為原型機、樣機),屬性值是一個普通的對象。附:之所以叫隱式,大概是因為proto里的方法是通過這種原型鏈的形式繼承過來的,自己沒定義卻可以使用。
? 所有的函數(shù),都有一個prototype(稱它為‘顯式原型’prototype翻譯為原型,雛形,藍本)屬性,屬性值也是一個普通的對象;
? 所有引用類型的proto屬性值都指向它的構(gòu)造函數(shù)的“prototype”屬性值
? 當試圖得到一個對象的某個屬性時,如果這個對象本身沒有這個屬性,那么回去它的proto(既它的構(gòu)造函數(shù)的prototype)中尋找
② 關(guān)于this在此場景的一個使用說明,無論是對象(或其他引用類型)自身的屬性還是從原型中得到的屬性,屬性中用到的this都指向該對象自身
③ 循環(huán)對象自身的屬性
var item
for (item in f){
// 高級瀏覽器已經(jīng)在 for in 中屏蔽了來自原型的屬性
// 但是這里建議大家還是加上這個判斷,保證程序的健壯性
if(f.hasOwnProperty(item)){
// 如果是自身的屬性就輸出
console.log(item);
}
}
① 以調(diào)用toString()方法為例
var f =new Foo('zhangsan',20); //通過構(gòu)造方法Foo創(chuàng)建了一個對象
f.toString()
→對象f(或其他引用類型)中沒有此方法
→去f的proto中查找(即構(gòu)造方法Foo.prototype中查找)
→仍然沒找到,而Foo.prototype本身是個對象,所去 Foo.prototype.proto中查找(即構(gòu)造方法Object.prototype)
→找到了toString()方法,執(zhí)行
② 注意:
?如果Object.prototype仍然沒有的話,會繼續(xù)去Object.prototype.proto中查找;
?不過js規(guī)定了Object.prototype.proto 返回的是null,這是特例,大概是防止這么無限循環(huán)下去吧;
③ instanceof方法工作原理:
a)定義:用于判斷引用類型是否屬于某個構(gòu)造函數(shù)
b)f instanceof Foo的判斷邏輯是:從f開始通過proto一層層往上,能否找到Foo.prototype (第一下就找到了,正確)
c)f instanceof Object 的判斷邏輯:從f開始通過proto一層層往上,能否找到Object.prototype (第二層找到了,正確)
d)注意:
?所有的引用類型都能匹配到Object這個構(gòu)造函數(shù),因為他們的隱式原型都是對象。
?這更加能理解數(shù)組和函數(shù)是一個特殊的對象,也是其構(gòu)造函數(shù)返回的對象跟我們自己寫個構(gòu)造方法創(chuàng)建一個對象的形式差不多,都是基于Object而來。
?官方定義: 在Javascript中,每一個函數(shù)實際上都是一個函數(shù)對象。
?new一個function 實際上是返回一個函數(shù)對象。這與其他的對象有很大的不同。其他的類型Array、Object等都會通過new操作符返回一個普通對象。盡管函數(shù)本身也是一個對象,但它與普通的對象還是有區(qū)別的,因為它同時也是對象構(gòu)造器,所有typeof返回 “function”的對象都是函數(shù)對象。因而,所有的構(gòu)造器都是對象,但不是所有的對象都是構(gòu)造器。
④ 可以修改Object這個類型來讓所有的對象具有一些通用的屬性和方法:
Function是所有函數(shù)對象的基礎(chǔ),而Object則是所有對象(包括函數(shù)對象)的基礎(chǔ),所有對象都由Object繼承而來。在JavaScript中,任何一個對象都是 Object的實例,因此,可以修改Object這個類型來讓所有的對象具有一些通用的屬性和方法,修改Object類型是通過prototype來完成 的:
以下是引用片段:
Object.prototype.getType=function(){
return typeof(this);
}
var array1=new Array();
function func1(a,b){
return a+b;
}
alert(array1.getType());
alert(func1.getType());
上面的代碼為所有的對象添加了getType方法,作用是返回該對象的類型。兩條alert語句分別會顯示“object”和“function”
var arr = [];
arr instanceof Array // true
// instanceof 只能用來判斷引用類型中的Array和 function ,原因見上文
// 另外typeof 是無法判斷是否是數(shù)組的,對于引用類型它只能區(qū)分function
typeof arr // object
?創(chuàng)建一個空對象,
?this指向這個對象,
?執(zhí)行代碼,即對this賦值,
?返回this
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 div1 = new Elem('detail-page');
//console.log(div1.html());
div1.html('<p> hello </p>').on('click',function(){
alert('clicked');
})
另:在實際工作中也經(jīng)常會在公用的js文件中給Date寫一個格式化時間的方法,例如Date.prototype.format = function(fmt) {...},然后新創(chuàng)建的Date對象就可以直接調(diào)用format方法了。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。