js提供了一些内置類,如Array String Function等,隻要有類就有原型。
1,function ,屬性包括 arguments, caller,length,name ,prototype,__proto__,
2,prototype,屬性又分為constructor: function () {},__proto__: Object,
3,__proto__從别的原型鍊繼承過來可以直接用的,prototype是要加在自己原型鍊上的,供别人調用,或者直接執行個體化後,别人可以直接調用轉成__proto__的。
__proto__是永遠存在的,都指向下一層,最終是Object。
4,function 和prototype本身都含__proto__,其實本身也都是對象,自己繼承過來的,他們2個也是基本類型的執行個體。
js的instanceof是根據prototype來判斷兩個對象是否存在繼承關系,A instanceof B, js會沿着A的原型鍊查找 直到找到A.__proto__ === B.prototype 傳回true。
一句話__proto__一層層都是指向繼承的,最終到基本類型上。
一,function
function定義的是一個Object(對象),而且還是一個很特殊的對象,這個使用function定義的對象與使用new操作符生成的對象之間有一個重要的差別。
這個差別就是function定義的對象有一個prototype屬性,使用new生成的對象就沒有這個prototype屬性。
prototype是function的一個屬性。所有通過function 來定義的對象,都有prototype這個屬性。
通過{}定義的對象字面量是沒有prototype的,如
var a ={1:"a"}
console.log (a.prototype);
結果是undefined,原因是他已經執行個體化,
var a ={1:"a"}
console.log (a.__proto__);
結果是 Object {} ,相當于new 後的。
函數的 length 屬性隻能得到他的形參個數,而無法得知實參個數。
function 是Object的執行個體,他自己的__proto__是Object.prototype
var A =function (age ){
this.age = age;
}
A.prototype.haha = function (){}
console.log( A instanceof Object)// true
console.log( typeof A) // function
console.log (Object.prototype.toString.call(A)) //[object Function]
數組類型typeof 是object,數組跟object更加接近
var B =[1,2,3]
console.log(typeof B)//object
console.log(typeof A)//function
var A =function (age ){
this.age = age;
}
A.prototype.haha = function (){}
var B =[1,2,3]
console.log(typeof A)//function
console.log(A instanceof Function)//true
console.log(A instanceof Object)//true
console.log(typeof B)//object
console.log(B instanceof Array)//true
console.log (Object.prototype.toString.call(A)) //[object Object]
caller:
傳回一個對函數的引用,該函數調用了目前函數。
functionName.caller
functionName 對象是所執行函數的名稱。
說明
對于函數來說,caller 屬性隻有在函數執行時才有定義。如果函數是由頂層調用的,那麼 caller 包含的就是 null 。如果在字元串上下文中使用 caller 屬性,那麼結果和 functionName.toString 一樣,也就是說,顯示的是函數的反編譯文本。
var A =function (age ){
this.age = age;
console.log(A.caller)
}
A.prototype.haha = function (){}
var B = function(type){
A();
}
B();
傳回,最後是B的函數,誰調用我了,傳回誰
function (type){
A();
}
arguments.callee :傳回正被執行的 Function 對象,也就是所指定的 Function 對象的正文。
[function.]arguments.callee
可選項 function 參數是目前正在執行的 Function 對象的名稱。
說明 : callee 屬性的初始值就是正被執行的 Function 對象。
callee 屬性是 arguments 對象的一個成員,它表示對函數對象本身的引用,這有利于匿名函數的遞歸或者保證函數的封裝性,例如下邊示例的遞歸計算1到n的自然數之和。而該屬性僅當相關函數正在執行時才可用。還有需要注意的是callee擁有length屬性,這個屬性有時候用于驗證還是比較好的。arguments.length是實參長度,arguments.callee.length是
形參長度,由此可以判斷調用時形參長度是否和實參長度一緻。
二、prototype
本身含constructor,__proto__
var A =function (age ){
this.age = age;
}
A.prototype.haha = function (){}
console.log (A.prototype) ;
可以看到的内容
Object {haha: function}
constructor: function (age ){
arguments: null
caller: null
length: 1
name: ""
prototype: Object
__proto__: function Empty() {}
<function scope>
haha: function (){}
__proto__: Object
constructor實際指向的是 函數建立時的那個function。
function Animal(name) {
this.name = name;
}
Animal.prototype = {
talk: function() {},
run: function() {}
}
function Dog(age,name) {
//Animal.call(this,name)
this.age=age;
}
// 要讓 Dog 繼承 Animal, 隻需:__ 2個_
Dog.prototype = new Animal ; // 執行個體化後
Dog.prototype.constructor = Dog;//手工的把constructor給暴露出來了。可以通過dog.constructor來調用
//Dog.prototype = new Animal ; //Animal的構造函數和自己的prototype也都放到Dog上
Dog.prototype.haha = function () {};//
Dog.prototype.haha.tata = 4;
var dog = new Dog("sdd","bbb");
var animal = new Animal("aaaa");
console.log(dog);
console.log(Dog.prototype);
傳回結果如下:

dog.__proto__.__proto__ === Animal.prototype 傳回的true。
原型鍊作為實作繼承的主要方法,其基本思想是:讓原型對象等于另一個類型的執行個體,這樣原型對象将包含一個指向另一個原型的指針,相應的,另一個原型中也包含着一個指向另一個構造函數的指針,假如另一個原型又是另一個類型的執行個體,如此層層遞進,就構成了執行個體與原型的鍊條,這個鍊條就稱之為原型鍊.
另外一個問題,prototype是存儲放到共享區域内的,可以共同修改。
Dog.prototype = Animal.prototype的方法內建,如果子類重寫了父類的方法,父類也會受到影響。
推薦的用法是
Dog.prototype.__proto__ = Animal.prototype
不用寫Dog.prototype.constructor = Dog了,constructor 沒有被覆寫,Dog本身就有了。
參考可以看下下面的例子
代碼
function Person(name)
{
this.name=name;
this.showMe=function()
{
alert(this.name);
}
};
Person.prototype.from=function()
{
alert('I come from prototype.');
}
var father=new Person('js');//為了下面示範使用showMe方法,采用了js參數,實際多采用無參數
alert(father.constructor);//檢視構造函數,結果是:function Person(name) {...};
function SubPer()
{
}
SubPer.prototype=father;//注意這裡
SubPer.prototype.constructor=SubPer;
var son=new SubPer();
son.showMe();//js
son.from();//I come from prototype.
alert(father.constructor);//function SubPer(){...}
alert(son.constructor);//function SubPer(){...}
alert(SubPer.prototype.constructor);//function SubPer(){...}
關于prototype是共享和prototype的作用域問題
function Tree(x){
this.value = x;
}
Tree.prototype.children = [1,2];
var a =new Tree(2);
a.children=3;
var b = new Tree(4);
b.children=5;
var c = new Tree(6);
console.log (c.children)//[1,2]
這個對 a.__proto_ 沒有做修改,最後依然是 a.__proto_ === Tree.prototype
a.children=3,相當于在a這個對象下面直接加了個children的屬性。
function Tree(x){
this.value = x;
}
Tree.prototype.children = [1,2];
var a =new Tree(2);
a.children.push("3");
var b = new Tree(4);
b.children.push("5");
var c = new Tree(6);
console.log (c.children);//[1,2,"3","5"]
a.children相當于開始是undefined,如果直接複制的話,就是在a對象下加屬性了,然後在.操作,相當于從原型鍊上去取了。
var A = function(b){
this.b =b;
}
A.prototype.hh="222";
$.extend(A.prototype,{
b:"333",
hh:"444"
});
var a = new A();
console.log(a);
- b: undefined
- __proto__: Object
- b: "333"
- constructor: function (b){
- arguments: null
- caller: null
- length: 1
- name: ""
- prototype: Object
- __proto__: function Empty() {}
- <function scope>
- hh: "444"