JS_Object和Function的區別
我們本次的解釋,主要通過下圖

粗看該圖,估計你不一定能看明白。不過接下來讓我逐行向你解釋。

- 最左側:意思是,有兩個對象f1和f2,他們是通過new Foo()出來的。
- 中間:Foo()就是最左側用到的Foo()
- 最右側:表示,函數Foo()的prototype屬性!
function Foo() {
}
var f1 = new Foo();
alert(f1.__proto__ == Foo.prototype); ?function Object(){[native code]}//Javascript自帶,不是自定義的,可以近似認為是基類
function Function(){[native code]}//Javascript自帶,不是自定義的,可以近似認為是基類
?
這里的這兩個function,分別走兩個方向,
Object作為了眾多object(實例,new出來的)的基類型
Function作為眾多function(主要是那些function出來的,就是定義出來的函數)的基類型
?
在開始下面更細致的解釋先,我們約定一些內容,Object代表這里所說的Object,object代表實例對象
,Function代表這里說的Function,function是關鍵字。對於Object與object的區別很好理解,一個是function,一個是new出來。
?
現在讓我們思考兩個問題:
第一個,當我們擴展Object原型時,new出來的Function,是否會被擴展?
第二個,當我們擴展Function原型時,由於Object也是個Function,那么其實例object是否會被擴展
?
先看第一個問題.eg.
?
Object.prototype.test4extend="123";//擴展Object的原型
document.write("Function:"+Function.test4extend);//在Function中出現了test4extend屬性
document.write("<br>")
document.write("Object:"+Object.test4extend);//在Object中出現了test4extend屬性,此時Object還是個Function
document.write("<br>")
var obj=new Object;
document.write("Object instance:"+obj.test4extend);//在obj中擴展了test4extend,此時的obj是object
document.write("<br>")
function Foo()
{
}
var foo = new Foo;
document.write("foo object:"+foo.test4extend);//foo對象上擴展上了test4extend屬性
document.write("<br>")
document.write("Foo Function:"+Foo.test4extend);//函數上也擴展上了test4extend屬性
document.write("<br>")
console.log("Object", Object);
console.log("Function", Function); ?注釋已經寫得很清晰了,通過以上幾點我們很容易發現以下幾點:
?
1、Object擴展了所有的object(obj,foo),與object擴展自Object是相符的。在這里更加驗證了。2、Object擴展了Function,這點說明Function擴展自Object,說明Object比Function更底層些。
3、Object擴展了自身的屬性,即Object.test4extend也是可以的。
這點說明,Object擴展了Function,又因為Object本身又是通過function定義出來的,所以會受到Function影響,所以,反過來Function又擴展了Object。
接下來看看第二個問題
Function.prototype.test4extend="123";//擴展Function的原型
document.write("Function:"+Function.test4extend);//在Function中出現了test4extend屬性
document.write("<br>")
document.write("Object:"+Object.test4extend);//在Object中出現了test4extend屬性,注意此時Object是個Function
document.write("<br>") var obj=new Object; document.write("Object
instance:"+obj.test4extend);//在obj中沒有擴展上test4extend,此時的obj是object
document.write("<br>") function Foo() { }
var foo = new Foo; document.write("foo
object:"+foo.test4extend);//foo對象上沒有擴展上test4extend document.write("<br>")
document.write("Foo Function:"+Foo.test4extend);//Function擴展上了test4extend屬性
document.write("<br>")
??
?這說明Function只管沒有被實例化得,被實例化的,他是沒有辦法管的。與Object不同,Object是無論是否實例化都管的。
接下來解釋這個圖:
先看最左側的__proto__虛線,表示Foo.__proto__相當於Function.prototype,這里和Object情況差不多,只是屬性一致而已,並不是指真正的那個Function
中間的下部的__proto__虛線,代表Function.__proto__等於Function.prototype,這里可是真的就是,和前面的相當於不同。
alert(Function.__proto__===Function.prototype);//true
?右側左上的__proto__虛線,代表Object.__proto__等於Function.prototype,這里可是真的就是,和前面的相當於不同。
alert(Object.__proto__===Function.prototype);//true
?
?右側右上的__proto__虛線,代表Function.prototype.__proto__相當於Object.prototype,只是屬性一致而已,並不是真的。
先讓我們總結下__proto__和prototype的區別和關系。
區別:從實際效果上來說,可以認為__proto__是用來擴展Function的,擴展出來的函數,可以直接調用,不需要new出對象才能用,同時對象是不會擴展通過__proto__擴展的方法或屬性的
function Foo() {
}
Foo.__proto__.test = "__proto__ test property found";// 通過__proto__擴展
Foo.__proto__.addextend = function() {
document.write("Foo add extend by __proto__");
document.write("<br>");
}
Foo.addextend();// 可以執行
var foo = new Foo;
document.write("Foo:" + Foo.test);// 可以訪問
document.write("<br>");
document.write(foo.addextend);// 未定義
document.write("<br>");
document.write("Foo instance:" + foo.test);// 未定義
document.write("<br>"); ?
?
?對於prototype來說,它是針對對象的,也就是Function是無法使用的,只有new出來的才能有效
?
function Foo()
{
}
Foo.prototype.test="prototype test property found";
Foo.prototype.addextend=function(){
document.write("Foo add extend by prototype");
document.write("<br>");}
document.write(Foo.addextend());//未定義
document.write("<br>")
var foo=new Foo;
document.write("Foo:"+Foo.test);//無法訪問
document.write("<br>")
foo.addextend();//可以執行
document.write("foo instance:"+foo.test);//找到了
document.write("<br>" ?
?
- ?在Object中__proto__是Function的prototype是Object。
- 在Function中__proto__是Function的prototype也是Object。
- 現在讓我們再來結合第三行的圖看一看。有如下關系。
Function.__proto__就是(===)Function.prototype
Object.__proto__就是(===)Function.prototype - Function的__proto__和prototype就是一個,擴展任何一個都是相同的效果。Object的__proto__就是Function.prototype。當我們擴展Object.__proto__時,就相當於擴展了Function.prototype和__proto__,反之亦然。
Object.__proto__.test4extend="123";//擴展Object的原型
?
alert("Function:"+Function.test4extend);//在Function中出現了test4extend屬性
?
alert("Object:"+Object.test4extend);//在Object中出現了test4extend屬性,此時Object還是個Function
?
var obj=new Object;
alert("Object instance:"+obj.test4extend);//未定義
?
function Foo()
{
?
}
?
var foo = new Foo;
alert("foo object:"+foo.test4extend);//未定義
?
alert("Function:"+Foo.test4extend);//函數上也擴展上了test4extend屬性 ?
?【總結】
Function擴展自Object,但是Function對Object又有影響,這是通過Object.__proto__就是(===)Function.prototype建立的聯系。記住這個聯系后,我們還要記住__proto__和prototype的區別,前者擴展的只可以被Function直接調用,后者擴展的只可以通過其實例調用。另外,還要注意__proto__和prototype的鏈的概念,這是因為,他們可以互相關聯,訪問到Function或Ojbect的內容。