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的文法定义还会有很多新奇的发现。

  • 相关阅读:
    LeetCode Best Time to Buy and Sell Stock
    LeetCode Scramble String
    LeetCode Search in Rotated Sorted Array II
    LeetCode Gas Station
    LeetCode Insertion Sort List
    LeetCode Maximal Rectangle
    Oracle procedure
    浏览器下载代码
    Shell check IP
    KVM- 存储池配置
  • 原文地址:https://www.cnblogs.com/yyrdl/p/5179240.html
Copyright © 2011-2022 走看看