ECMAScript 5.1 Edition DOC 學習筆記

JerBurdge 8年前發布 | 11K 次閱讀 Prototype JavaScript開發

來自: http://www.cnblogs.com/yyrdl/p/5179240.html

先回顧一下ES5,畢竟在應用最多的瀏覽器端對ES6的支持不是很完善。即使有bable,traceur這樣的庫允許我們使用ES6的語法寫前端,但就其實質來講,最終還是把代碼翻譯成了ES5(更下還有ES3).那為何不直接使用ES5呢。還有就是翻譯之后的代碼面臨性能問題。比如{let a=12;}這樣ES6的局部變量聲明,在ES5(ES3也行)則是使用try{ throw undefined }catch(a){a=12}這樣的方式來實現的。let使用的越多,翻譯后的代碼中的try catch就越多,如果將var全都替換成let,那不可想象。

</div>

1.類型

  • string

  • number

  • object

  • boolean

  • null

  • undefined

  • symbol (es6)

attention : (typeof null) 值為 'object', (typeof undefined)值為:'undefined',其余的如自己所想。

null的定義:primitive value that represents the intentional absence of any object value.用來表示故意

丟失的一個對象類型(object類型)的值(即某一個變量container里面存儲的值應該是object類型,但是未賦予,所以使用null來代替)。

這也解釋了 typeof null='object'. null 也是一個值!! undefined 表示一個變量未賦予任何值,或是不存在。

undefined: primitive value used when a variable has not been assigned a value

P roperties are containers that hold other objects, primitive values, or functions. A primitive value is a member of one of the following built-in types: Undefined, Null, Boolean, Number, and String; an object is a member of the remaining built-in type Object; and a function is a callable object. A function that is associated with an object via a property is a method.

很多人說js里面全是對象,這是不嚴謹的。這段話可以表明js里面的值分為三類:object,primitive values,function。primitive value是像 123 或是 "hello" 等這樣基本的值;

function 屬于上面7種基本類型中的object,由于其特殊性,單獨列出來;object就是object. Function和Object的關系后面會詳細論述。(其實Array,Number等這些內嵌的原型都是非常原始的,和Object擁有共同的原型)

這幾個是基本的類型。snippet of code below:

  var a=232;//字面量,number類型,不可以給他定義屬性或方法

a.type_name="number";//這步有執行,會將a當成一個對象創建,

//并賦予type_name屬性和值,但創建之后立即銷毀

console.log(a.type_name);//undefined

//morefurther

var a=232;

var q=(a.type_name="number");

console.log(a);//232

console.log(a.type_name);//undefined

console.log(q);//'number'

//</pre>

代碼中的 232 稱為字面量,這是一個number類型的字面量,字面量的類型不可改變,但可以向其他類型轉換。

var a; 在js中看成是聲明一個存儲數據的容器,沒類型和大小限制。typeof a;不是測試 a 的類型,而是測試

放在 a 這個容器中的值的類型。

上面出現的 typeof 運算符是用于檢測一個值的基本類型,若要檢測一個值是哪一個類的實例,使用 instanceof 運算符。這個運算符會遍歷該對象的原型鏈,直至為'true'才停止,若到原型鏈的頂層都不為真的話,則結果為 false , js 中所有對象的原型鏈頂端都是自 Object.prototype 這個值,至于這個值是什么,后面會提到, 因此js中的任何對象 obj``Object 的一個實例。 typeof 也可以檢測一個值是否是 function ,function不是基本類型,屬于對象,但是卻能用 typeof 檢測,這也是js函數特殊的另一個地方。

 var str='s';

str instanceof Object;// false, 's'為基本類型中的string,并不是對象

str instanceof String;// false. 's' 不是對象

typeof str;//'string' ,string類型

//but

(new String(str)) instanceof String;//true; 顯示轉換成了String對象

</pre>

一般對象的 toString 方法返回的值為 string 基本類型,非對象。 String(23223) 或是 Number('4555') 這樣的用法不要認為是

調用對象的構造函數,這其實相當于C++里面的強制類型轉換。說到這里想提一下js的顯示和隱式類型轉換,礙于篇幅,就省略了。

還有好多內容需要說一下。

2.對象

上面提到 instanceof 運算符,這個牽扯到原型鏈,在討論完對象之后自然會明白了。

2.1 創建對象

objects may be created in various ways including via a literal notation or via constructors which create objects and then execute code that initialises all or part of them by assigning initial values to their properties.

js中的對象可通過字面量創建,也可以通過構造函數創建。

  • 通過字面量:

   var obj1={

      x:1

 };</pre> 

文法定義為:

  ObjectLiteral :

 { }

 { PropertyNameAndValueList }

 { PropertyNameAndValueList , }

PropertyNameAndValueList :

 PropertyAssignment

 PropertyNameAndValueList , PropertyAssignment

PropertyAssignment ://這兒非常有意思

 PropertyName : AssignmentExpression

 get PropertyName ( ) { FunctionBody }

 set PropertyName ( PropertySetParameterList ) { FunctionBody }

PropertyName :

 IdentifierName

 StringLiteral

 NumericLiteral

PropertySetParameterList :

 Identifier</pre> 
  • 通過構造函數:

     function Foo(){//the constructor

    this.name='fool guy';

    this.sayHello=function(somebody){// another way to add a method

      console.log("Hello "+somebody);

    }

}

Foo.prototype.shakeHand=function(){// a way to add a method

 //nothing to do ,just say some words

  console.log("Lets shake hand");

}

var fool=new Foo();</pre>

解釋一下上面那段代碼的過程。首先我們定義了一個Foo類,并且通過prototype為其添加了一個

shakeHand方法。然后在constructor里面定義了倆個另外倆個屬性,其中一個也是可執行的方法。這里我們實際

上定義了倆個方法。那這倆個方式有什么區別呢。通過prototype添加的屬性或是方法在構造函數執行之前

就已經存在,是每個Foo實例默認就有的。而constructor里面定義的,必須在constructor執行之后才會有。

constructor一定會執行的,所以從效果上來講一致。

上面的那個Foo對象實例化的過程實際如下面代碼所示:

    function Foo(){

}

Foo.prototype.shakeHand=function(){// a way to add a method 

 //nothing to do ,just say some words

  console.log("Lets shake hand");

}

function createFooObject(){

    var obj=new Foo();

    obj.name='fool guy';

    obj.sayHello=function(somebody){

        console.log("Hello "+somebody);

    }

    return obj;

}

var fool=createFooObject();</pre> 

和下面這種方式存在區別:

    function Foo(){//the constructor

}

Foo.prototype.name='fool guy';

Foo.prototype.sayHello=function(somebody){// another way to add a method

      console.log("Hello "+somebody);

    };

Foo.prototype.shakeHand=function(){// a way to add a method 

 //nothing to do ,just say some words

  console.log("Lets shake hand");

}

var fool=new Foo();</pre>

2.2 對象繼承

2.2.1 原型繼承

    //child class

function Child(sex){

    this.sex=sex;

    this.name='';

    this.age='';

    this.selfDescription='';

}

Child.prototype.isBoy=function(){

    return this.sex.toLowerCase()=='boy';

}

Child.prototype.isGirl=function(){

    return this.sex.toLowerCase()=='girl';

}

Child.prototype.selfIntro=function(){

    console.log("I am "+this.name+","+"I am "+this.age+" years old."+this.selfDescription);

}

//then the boy class

function Boy(name,age,description){

    this.name=name;

    this.age=age;

    this.selfDescription=description;

}



Boy.prototype=new Child("boy");//



//two Boy instances



var boy=new Boy('Mike',12,"I am not a naughty boy!");

boy.selfIntro();

//I am Mike,I am 12 years old.I am not a naughty boy!



var Jason=new Boy("Jason",22,"Nice to meet you:)");

Jason.selfIntro();

//I am Jason,I am 22 years old.Nice to meet you:)</pre> 

哈哈,自我感覺我這個代碼設計的不錯 :)

Boy.prototype=new Child("boy") 這句即為原型繼承的關鍵,用自然語言解釋就是:我,Boy類是以Child類為原型的,我繼承了Child的屬性和method。

這就像你看到某部小說是以誰誰誰為原型一樣,小說主人公肯定會繼承寫作對象的一些特性。

然后通過這里可以看出,原型繼承一次只能繼承一個父類,如果再使用 Boy.prototype=new ..... 的話,之前的就會被抹去。因此想要繼承多個父類,還得使用另外的

辦法。之后討論這個問題。

這里有一點需要明白,我們在之前討論過,使用構造函數創建對象時,每創建一個對象構造函數都會執行一次,在C++中,基類的構造函數也會每次都執行,順序我忘了。那這里呢?通過上面的代碼其實也可以猜到 Boy.prototype=new Child("boy") 基類在這兒初始化的時候執行一次,

之后就不會執行了,而子類的構造函數在每次實例化的時候都會執行。所以基類和子類的構造函數的執行順序是先執行基類后執行子類。

所以在這里我們完全不用擔心基類的構造函數會把 name , age 等屬性轉成 undefined .

2.2.2 類繼承

ES5中是無類這個概念的,取而代之的是原型這個概念。不過為了明白易懂,借用類的概念。在ES6中新增了類,之后再討論,先回顧一下ES5的內容。

類繼承實際上是使用 call 或者 apply ,在子類的構造函數里使用 BaseClass.apply(this,args) 的方式,使得子類獲得在 BaseClass 中定義的

屬性(這里的 BaseClass 是一個函數,base constructor).

嚴格意義上講,這算不上繼承,由于是將基類的 this 設成了指向子類的 this ,只是在 BaseClass 里又對子類附著了一些屬性而已。

這種方式無法使子類擁有基類通過 prototype 定義的屬性和方法,更滿足不了 instanceof 運算符的檢測。

結論:這玩意兒只是看起來像繼承!

網上還有什么組合方式繼承,沒有必要說了。

2.2.3 Object.create(O[,Properties])

The create function creates a new object with a specified prototype. When the create function is called, the following steps are taken:

  • If Type(O) is not Object or Null throw a TypeError exception.

  • Let obj be the result of creating a new object as if by the expression new Object() where Object is the standard built-in constructor with that name

  • Set the [[Prototype]] internal property of obj to O.

  • If the argument Properties is present and not undefined, add own properties to obj as if by calling the standard built-in function Object.defineProperties with arguments obj and Properties.

  • Return obj.

Object.create()的工作方式如上面的引言所示,將會以傳入的對象作為原型創建一個新的對象,如果有附加屬性的話,附加屬性將會添加到這個新創建的對象上。

和下面這段代碼效果一致:

```javascript

 function create(){

if(arguments.length<1||(typeof argumets[0])!=='object'||arguments[0]==null)

{

  throw TypeError("The first argument must be an object!!");

}

function slave(){};

slave.prototype=arguments[0];

var o=new slave();

if(arguments[1]){

 Object.defineProperties(o,arguments[1]);

}

return o;

}</pre>

```

2.2.4 Further on

```javascript

function A(){

this.sex="A";

}

A.prototype.sayA=function(){

console.log("I am A");

}

A.prototype.constructor=A;

A.name1='A';

function B(){

this.name="232";

}

B.prototype=new A();

B.prototype.constructor=B;

B.prototype.sayB=function(){

console.log("I am B!");

}

B.name1="B";

function C(){

}

C.prototype=new B();

C.prototype.constructor=C;

C.prototype.age=12;

C.prototype.say=function(){

console.log("age:"+this.age);

console.log("name:"+this.name);

console.log("sex:"+this.sex);

this.sayA();

this.sayB();

}

C.name1="C";

var cc=new C();

console.log("*C*");

cc.say();

console.log(cc.constructor);

console.log(cc.proto);

console.log(cc.proto.constructor.name1);//B

console.log(A.prototype.isPrototypeOf(cc));//true

console.log(cc.proto=== C.prototype);//true</pre>

```

這段代碼可以貼到瀏覽器中運行一下,就倆個地方需要特別注意:

  • A.name1="A"

```javascript

//or

B.name1="B";

C.name1="C";</pre>

```

在js中函數也是對象,這里的A,B,C雖然是三個類的構造函數,但其本身也是對象,我們可以往上附加屬性。但是這些屬性值不會被子類繼承。但可以像代碼中展示的那樣訪問: cc.__proto__.constructor.name1

  • C.prototype.constructor=C

  B.prototype.constructor=B;

這是顯示指明該類的構造函數,如果不指明的話, cc.constructor 返回的結果是A(如果B有指明自己的構造函數是B,那么就是B)。雖然 new C() 的時候確實會執行C,而且C確實是實際意義上的C的構造函數,但是 cc.constructor 就不返回函數C,這是不合理的。所以在定義的時候還是顯示指明一下構造函數。

2.3 prototype 和 __proto__

這里出現了 prototype ,關于 prototype 和 __proto__ 網上有很多人寫的博客,然而大部分都是bullshit,沒看到過講明白的。

2.3.1 prototype

Each constructor is a function that has a property named “prototype” that is used to implement prototype-based inheritance and shared properties.

這個是對prototype的官方解釋。這句話表明了倆點,一個是誰會有prototype這個屬性,另外就是prototype這是屬性的意義在哪里。

作為一個類的構造函數的函數具有這一個屬性(其實解釋器不確定哪一個函數會作為構造函數,所以基本上是function都有

這個屬性,在未往上面賦值前為一個空對象,但不是undefined)。這一屬性是用來實現基于原型的繼承,并通過

它共享原型的屬性(理解為C++里面共享多個父類的method和屬性值)。

結合上面對于通過構造函數創建對象的分析, prototype 就好理解了. prototype 被設計來實現原型繼承,同時實現屬性共享。

2.3.2 __proto__

Every object created by a constructor has an implicit reference (called the object’s prototype) to the value of its constructor’s “prototype” property.

這里的implict reference 即 __proto__ , 說的很明白了,指向其直接父類的構造函數的 prototype 屬性。參照上面定義的A,B,C三個類:

   cc.proto===C.prototype;//true

cc.proto.proto===B.prototype;//true

cc.proto.proto.proto=A.prototype;//true</pre>

2.3.3 原型鏈

Furthermore, a prototype may have a non-null implicit reference to its prototype, and so on; this is called the prototype chain.

這是官方文檔中對原型鏈的解釋(和 __proto__ 還有 prototype 的官方解釋連起來理解)。在上一段代碼中實際上已經展示了如何使用原型鏈。你可以將原型鏈理解成家族族譜,家族族譜是樹形結構,而訪問原型鏈只能從子類往父類依次訪問,即從樹形結構的葉子往根訪問。現在讓我們通過原型鏈來訪問一下A類構造函數的 name1 屬性。

   var name1=cc.proto.proto.proto.constructor.name1;

console.log(name1);//'A'</pre>

對象查找一個屬性的時候是從原型鏈的底端(子類)往上(父類)查詢,一旦找到一個同名的就結束。比如

   cc.sayA();

sayA 是在A類上定義的,解釋器先去查找cc是否后來添加了這條屬性,沒有再順著原型鏈去查找C類中是否定義了 sayA ,沒有的話繼續往上找,直到找到一個名為 sayA 的屬性。由于這個原因:

    delete cc.sayA;

cc.sayA();//'I am A';</pre> 

sayA 這個method仍可以訪問,因為父類上的 sayA 并未刪除,所以要徹底刪除的話,只能去父類上刪除。我們也可以這樣做:

     cc.sayA=undefined;//并不影響父類

雖然設成了 undefined 但是這個屬性仍然存在, "sayA" in cc 值為 true ,達到了delete類似的效果。(PS:delete 某個屬性之后,這個屬性是不存在的)

2.4 Object 和 Function

這是js種倆個基本且非常重要的對象。

2.4.1 Object

先說底層的ToObject()方法,若傳入的是null或是undefined則報錯,若傳入的是一個對象,則直接返回這個對象(引用),若是基本類型中的 number , string , boolean ,則將其轉為相應的內嵌對象(Number,String,Boolean)。所以 new String("str") 完全可以簡寫為 Object("str") ,同理對于 new Number(123) ;,但是注意 new Number("123") ,會將字符串“123”轉為數字。所以 new Number("123") 等價于 Object(Number("123")) ;

對象屬性的屬性:

  • value 這個屬性的值

  • writable 屬性值是否可修改

  • configurable 屬性是否可配置

  • enumerable 屬性是否可枚舉

自有屬性和繼承屬性

  • inherited property

繼承的屬性

  • OwnProperty

非繼承的屬性

上面這個定義雖然明白還是不夠清楚

   function A(){

 this.x=1;

}

A.prototype.y=2;

function B(){

 this.z=3;

}

B.prototype.f=4;

var b=new B();

b.g=5;

//b的g和z屬性都是自有屬性,f和y都是繼承屬性

//請思考x 是b 的什么屬性,以及為什么</pre>

then Object

  • Object() 底層調用ToObject(),

  • new Object() 底層也是調用ToObject()方法

  • Object.create()

  • Object.prototype

Object對象的原型,我們知道prototype是一個object類型,Object是最原始的對象,他的prototype又是一個對象,這是什么邏輯。ECMA的解釋是

The initial value of Object.prototype is the standard built-in Object prototype object

即Object.prototype是一標準內嵌的Object prototype對象,仍是object類型,一個特殊的對象。

The value of the [[Prototype]] internal property of the Object prototype object is null, the value of the [[Class]] internal property is "Object", and the initial value of the [[Extensible]] internal property is true.

所以 Object.prototype.__proto__ 的值應該是 null .

  • Object.prototype.constructor

The initial value of Object.prototype.constructor is the standard built-in Object constructor.

Object的構造函數是標準內嵌的。(Object 首先是一個可執行的函數,即Object類的構造函數,Function和Object的關系后面討論)

  • Object.defineProperty(O,P,Attribute)

定義一個對象的某一個屬性的屬性:

    var obj={x:1};

Object.defineProperty(obj,"x",{

   value:10,

   writable:false,

   enumerable:false,

   configurable:false

});

console.log(obj.x);//10

obj.x=90;

console.log(obj.x);//10

delete obj.x;

console.log(obj.x);//10</pre> 

如果是在strict模式下 obj.x=90 和 delete obj.x 都會報錯。有些人抱怨js的值太隨意了,使用這一方法可以讓js的對象表現得更為嚴謹。

  • Object.defineProperties(O,Properties)

    var obj={x:1,y:9};

Object.defineProperties(obj,{

  "x":{

      "value":10,

      "writable":false

  },

  "y":{

      "enumerable":false

  }

});

for(var p in obj){

   console.log(p+" : "+obj[p]);

}

// x : 10</pre> 
  • Object.seal ( O )

將指定對象設置成不可擴展 configurable:false ,一旦設置,不可更改

  • Object.freeze ( O )

將指定對象設置成只讀且不可擴展

  • Object.preventExtensions(O)

將對象底層的 extensible 屬性設置成false,這樣就不可以再在這個對象上添加另外的屬性了。 configurable 為 false 時也會自動將底層的 extensible 設置成 false

  • Object.isSealed ( O )

  • Object.isFrozen ( O )

  • Object.isExtensible ( O )

  • Object.keys(O)

返回指定對象的可枚舉屬性的名字組成的數組。

  • Object.getOwnPropertyNames ( O )

返回指定對象的自有屬性的名字組成的數組。(涵蓋可枚舉屬性)

  • Object.getOwnPropertyDescriptor ( O, P )

返回指定對象的指定自有屬性的描述(value,writable等信息)

  • Object.prototype.toString ( )

如果該值是 undefined 返回 '[object Undefined]' ,其他的返回 "[object +類名]" ,類名首字母大寫。如果是自己寫的類,類名統一為 "Object" .js不提供方法去設置類名。js定義的類有:"Arguments", "Array", "Boolean", "Date", "Error", "Function", "JSON", "Math", "Number", "Object", "RegExp", and "String".

  • Object.prototype.hasOwnProperty (V)

檢測該對象是否具有屬性v,ECMA定義了他的工作過程,按官方描述應該如下代碼所示:

    Object.prototype.hasOwnProperty=function(v){

   return ToObject(this).getOwnProperty(v)?true:false;

}</pre> 

PS: ToObject和getOwnProperty 是js解釋器使用的方法,不對外暴露。

  • Object.prototype.isPrototypeOf (V)//語義很清楚

  • Object.prototype.propertyIsEnumerable (V)

Object.method和Object.prototype.method的區別通過前面關于類繼承的內容可以明白。

2.4.2 Function Objects

title是Function Objects 是強調Function 是特殊的object. 待會兒有個技術會亮瞎雙眼。

  • Function()

  • new Function (p1, p2, … , pn, body)

功能和Function()一致,返回一個Function對象。親可以先去看看 ECMA的文檔 .

先來一段代碼:

   var x=1;

function func(){

 var body='return x*100+10*y+z;';

 return Function("y","z",body);

}

console.log(func()(3,4));//134</pre>

按文檔寫的工作原理也可以這樣:

   var x=1;

function func(){

 var body='return x*100+10*y+z;';

 return Function("y,z",body);

}

console.log(func()(3,4));//134</pre>

這個功能和 eval 類似,唯一的不足是得到的Function 的 lexical Evironment 是 global Evironment.即下面這段代碼的結果仍然是 134

   var x=1;

function func(){

 var x=2;

 var body='return x*100+10*y+z;';

 return Function("y,z",body);

}

console.log(func()(3,4));//134</pre>

js未提供任何可以操縱scope的方法。

  • Function.constructor

Function 的構造函數是其本身

  Function===Function.constructor;//true
  • Function.prototype.call()
  • Function.prototype.apply()
  • Function.prototype.bind()
    這個函數返回一個函數對象,但這個對象比較特殊,沒有 prototype,Scope,FormalParameters,Code 這幾個內部屬性。
  • </ul>

    2.4.3 Function && Object && Obeject prototype object && Function prototype object

    啊,復雜的東西來了!研究這個就像去研究別人家的族譜一樣,各種考證!

    先來一個讓你頭暈的事實:

       Function instanceof Object;//true

    Object instanceof Function ;//true</pre>

    網上的有人說:js中一切的一切都是對象(錯),都繼承自Object(錯,不嚴謹),或者說原型鏈的根節點都是Object.prototype(對)

    instanceof 顧名思義,是誰的一個實例。其運作方式見 文檔 ,底層調用 HasInstance 方法. HasInstance 方法的工作方式如下:

    Assume F is a Function object.

    When the [[HasInstance]] internal method of F is called with value V, the following steps are taken:

    If V is not an object, return false.

    Let O be the result of calling the [[Get]] internal method of F with property name "prototype".

    If Type(O) is not Object, throw a TypeError exception.

    Repeat

    Let V be the value of the [[Prototype]] internal property of V.

    If V is null, return false.

    If O and V refer to the same object, return true.

    </div>

    即instanceof的左操作數的原型鏈中有一個和右操作數的 prototype 值一致,則返回 true ,否則 false .若右操作數不是某個類的構造函數(其實有 prototype 屬性就可以),拋出類型錯誤。

    __Object__的 prototype :

    Object.prototype 的初始值為 Object prototype object ,這個 Object prototype object 是一個標準內嵌的對象,相當于js中所有對象的太太太太太爺爺。 Object prototype object 的原型是 null (即 Object.prototype.__proto__===null 為真).

    __Function__的 prototype :

    Function.prototype 的初始值為 Function prototype object ,這個 Function prototype object 也是一個標準內嵌的對象,他的原型是 Object prototype object .即有:

       Function.prototype.__proto__===Object.prototype;//true

    但是這個并不是 Function instanceof Object 值是 true 的原因.真正的原因是:

        Function.__proto__.__proto__===Object.prototype;//true

    若之前你沒有理解 __proto__ 和 prototype 的區別的話,建議返回上面再看看。

    下面讓我們把事情弄清晰點:

        function Function(){

    }
    Function.prototype=Function prototype object;
    Function.prototype.constructor=Function;
    
    
    function Object(){
    
    }
    Object.prototype=Object prototype object;
    Object.prototype.constructor=Object;</pre> 
    

    Function 這個構造函數也是以 Function prototype 這個特殊對象為原型創建.這解釋了:

       Function.proto.proto===Object.prototype;//true

    //Function的原型是Function prototype這個特殊對象,而這個對象的原型是

    //Object prototype這個特殊對象,然后Object的prototype的屬性值是

    //Object prototype。也即 Function instanceof Object為真的理由。</pre>

    在js引擎里面 Object 這個構造函數是以 Function prototype object 為原型創建,所以有:

          Object.proto===Function.prototype;//true

      //這是 Object instanceof Function為真的原因</pre> 
    

    然后設置 Object 這個構造函數的 prototype 屬性為 Object prototype 這個特殊的對象,并設置 constructor 。像 Object.create 這樣的函數是附著在 Object 這個構造函數(對象)上的屬性,不被子類繼承。(之前的A,B,C類的時候有講)然后js引擎還在 Object.prototype 上定義了其他可以被繼承的方法或屬性。

    這里分析的依據在ecma的文檔里并沒有明確指出,網上有一個解釋這個的圖也沒有說清楚,證據如下:

    Object 這個構造函數是 Function prototype 的實例的理由:

         Object.__proto__===Function.prototype;//true

    另外ECMA文檔指出了 Function prototype 和 Object prototype 這倆個特殊的對象,詳情見ECMA文檔里對 Function 和 Object 的解釋。

    通過上面的分析,我們弄清楚了js中對象的關系,這對深入理解js非常重要。比如你就會明白為什么下面的代碼的返回值為真:

         Object.prototype.isPrototypeOf(Function.prototype);//true

     //等價于
    
     Funtion.prototype instanceof Object;//true
    
     //還有
    
     Function instanceof Function;//true.
    
     //Function.__proto__是Function prototype這個對象
    
     //Function.prototype的值也是Function prototype這個對象,所以。。。。。。
    
     Object instanceof Object;//true
    
     //Object.__proto__是Function prototype這個對象
    
     //Function prototype這個對象的原型是 Object prototype這個對象
    
     //Object.prototype的值為Object prototype這個對象,所以.....</pre> 
    

    然后原型鏈,繼承什么的都是小菜一碟了。之后就還剩閉包和ES6新增的內容啦:) 其實還有很多細節問題,比如js中 () 的作用是什么,可以往其中放什么內容,有沒有返回值。仔細看js的文法定義還會有很多新奇的發現。

    </div>

     本文由用戶 JerBurdge 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
     轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
     本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!