zoukankan      html  css  js  c++  java
  • ECMAScript 5.1 Edition DOC 学习笔记

    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


    Properties 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'
    
     //
    
    

    代码中的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对象
    
     
    
    

    一般对象的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
    
         };
    
    

    文法定义为:

    
      ObjectLiteral :
    
         { }
    
         { PropertyNameAndValueList }
    
         { PropertyNameAndValueList , }
    
      PropertyNameAndValueList :
    
         PropertyAssignment
    
         PropertyNameAndValueList , PropertyAssignment
    
      PropertyAssignment ://这儿非常有意思
    
         PropertyName : AssignmentExpression
    
         get PropertyName ( ) { FunctionBody }
    
         set PropertyName ( PropertySetParameterList ) { FunctionBody }
    
      PropertyName :
    
         IdentifierName
    
         StringLiteral
    
         NumericLiteral
    
      PropertySetParameterList :
    
         Identifier
    
    
    • 通过构造函数:
    
         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();
    
    

    解释一下上面那段代码的过程。首先我们定义了一个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();
    

    和下面这种方式存在区别:

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

    哈哈,自我感觉我这个代码设计的不错 :)

    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()的工作方式如上面的引言所示,将会以传入的对象作为原型创建一个新的对象,如果有附加属性的话,附加属性将会添加到这个新创建的对象上。

    和下面这段代码效果一致:

    
        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;
    
        }
    
    
    2.2.4 Further on
    
        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
    
    

    这段代码可以贴到浏览器中运行一下,就俩个地方需要特别注意:

    • A.name1="A"
    
       //or 
    
       B.name1="B";
    
       C.name1="C";
    
    

    在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
    
    
    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'
    
    

    对象查找一个属性的时候是从原型链的底端(子类)往上(父类)查询,一旦找到一个同名的就结束。比如

    
       cc.sayA();
    
    

    sayA是在A类上定义的,解释器先去查找cc是否后来添加了这条属性,没有再顺着原型链去查找C类中是否定义了sayA,没有的话继续往上找,直到找到一个名为sayA的属性。由于这个原因:

    
        delete cc.sayA;
    
        cc.sayA();//'I am A';
    
    

    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 的什么属性,以及为什么
    
    

    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
    
    

    如果是在strict模式下obj.x=90delete 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
    
    
    • Object.seal ( O )

      将指定对象设置成不可扩展configurable:false,一旦设置,不可更改

    • Object.freeze ( O )

      将指定对象设置成只读且不可扩展

    • Object.preventExtensions(O)

      将对象底层的extensible属性设置成false,这样就不可以再在这个对象上添加另外的属性了。configurablefalse时也会自动将底层的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;
    
        }
    
    

    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
    
    

    按文档写的工作原理也可以这样:

    
       var x=1;
    
      function func(){
    
         var body='return x*100+10*y+z;';
    
         return Function("y,z",body);
    
      }
    
      console.log(func()(3,4));//134
    
    

    这个功能和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
    
    

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

    • Function.constructor

      Function 的构造函数是其本身

    
      Function===Function.constructor;//true
    
    
    • Function.prototype.call()
    • Function.prototype.apply()
    • Function.prototype.bind()
      这个函数返回一个函数对象,但这个对象比较特殊,没有prototype,Scope,FormalParameters,Code这几个内部属性。
    2.4.3 Function && Object && Obeject prototype object && Function prototype object

    啊,复杂的东西来了!研究这个就像去研究别人家的族谱一样,各种考证!

    先来一个让你头晕的事实:

    
       Function instanceof Object;//true
    
       Object instanceof Function ;//true
    
    

    网上的有人说: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.

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

    Function这个构造函数也是以Function prototype这个特殊对象为原型创建.这解释了:

    
       Function.__proto__.__proto__===Object.prototype;//true
    
       //Function的原型是Function prototype这个特殊对象,而这个对象的原型是
    
       //Object prototype这个特殊对象,然后Object的`prototype`的属性值是
    
       //`Object prototype`。也即 Function instanceof Object为真的理由。
    
    

    在js引擎里面Object这个构造函数是以Function prototype object为原型创建,所以有:

    
          Object.__proto__===Function.prototype;//true
    
          //这是 Object instanceof Function为真的原因
    
    

    然后设置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 prototypeObject prototype这俩个特殊的对象,详情见ECMA文档里对FunctionObject的解释。

    通过上面的分析,我们弄清楚了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这个对象,所以.....
    
    

    然后原型链,继承什么的都是小菜一碟了。之后就还剩闭包和ES6新增的内容啦:) 其实还有很多细节问题,比如js中()的作用是什么,可以往其中放什么内容,有没有返回值。仔细看js的文法定义还会有很多新奇的发现。

  • 相关阅读:
    xml在html中的使用
    getElementsByTagName的用法
    opener 的使用
    动态增加属性
    innerText, innerHTML,outerHTML
    button的css属性
    动态改变select中option的次序
    input 的样式
    zkw线段树
    接着吐槽(2012/5/23)
  • 原文地址:https://www.cnblogs.com/yyrdl/p/5179240.html
Copyright © 2011-2022 走看看