JavaScript学习路上---js 核心概念

来源:互联网 发布:阿振网络随笔 编辑:程序博客网 时间:2024/06/05 06:49

基于对象的。

   原始类型,对象。对象分为普通对象和函数类型的对象。

   普通对象的创建:通过函数可以new出普通js对象。var a={};是一种简写形式, 也可以得到普通对象,在内部会转化成new Object()。 

   函数对象的创建: function a(){}; var a=function(){}; var a=new Function(); 前2种是简写形式,在内部都转化成第三种形式。

归根结底,一切函数对象都是由new Function(); 创建的。可以,在内部,对象都是通过new来创建的。

   普通对象是属性-值 对的集合,不能执行执行;

   函数对象包含了创建普通对象的可执行代码,可以执行用来创建普通对象或者执行用来完成一定的功能。

 

对象创建的通用规律: 在执行任意类似varx = new X()时,都会把X的prototype赋给x的__proto__,也就是说,x.__proto__和X.prototype此时会指向同一个对象。

 

   函数对象创建过程:

           1.创建一个函数对象 new Function。

           2.为该函数对象附加Construct属性(私有,不可访问),该属性也是一个函数,构建该函数对象的普通对象时会调用它。

           3.为该函数对象附加call属性,该属性是个function(通过native code实现的)。

          4 .给该函数对象附上_proto__(私有,ie下不可访问,用于形成原型链),将Function 函数对象的prototype(也是预定义好的)赋值给_proto__。

          5. 附加prototype属性:先用new Object()创建一个空对象,为这个对象创建一个属性叫constructor指向该构造函数对象本身,最后将该对象赋值给prototype属性。

           6 . 创建Scope,Length等属性

 

普通对象创建过程:function A(){this.p = 1};var a = new A()。 new A()会调用A这个函数对象的Construct函数,然后在该函数中做以下操作:

      1.创建一个普通对象(可能为空对象)。

       2.   将A.prototype(一般是一个普通对象)赋值给该对象的__proto__属性

       3. 调用A.call(x),x代表当前对象,即this。 在call方法中会执行我们在函数体中自定义的初始化代码(如:this.p=1;}  ),并且将x传给this。所以,在内部,函数对象也是属性-值对的集合。函数对象的call方法会回调我们在函数体中自定义的初始化代码以为该新对象增加属性。

      4. 返回构造的普通对象给a。但是,若在函数体里有return'返回的东西,它的类型(typeof)是个object,那么返回给a的普通对象将是return 语句返回的对象。

 

 

__proto__和prototype

   任意一个普通对象,都会有__proto__属性,指向该构造函数的prototype属性。注意__proto__是个私有属性,在IE上是看不到的。

   任何一个函数对象不仅有__proto__属性,还有prototype属性,该属性是用new Object()构建出来的,初始公开属性只有一个constructor。

 

原型链-继承:__proto__.__proto__.__proto__

     var base= new Base(); base是一个普通对象,其__proto__属性等于Base.prototype; Base.prototype默认是new Object()出来的一个普通对象(含有一个constructor公开属性)。任何new Object() 操作都会将当前对象的__proto__设置成Object.prototype,所以base.__proto__.__proto__的值分别是: Base.prototype,Object.prototype。  

所有原型链的顶端,最终都指向了Object.prototype。

另外,由于任意对象t的原型链的顶端都是Object.prototype(预定义好了的)。所以,Object.prototype里定义的属性,就会通过原型链,被所有的对象t继承下来。这样,预定义好的Object.prototype,就成了所有对象的“基类”。这就是原型链的继承。

    

看上图,Object.prototype已经预定义好了一些属性,我们再追加一条属性叫propertyA,那么这个属性和预定义属性一样,都可以从base上读到。

 

 

原型链实现继承: 任何一个js对象,都有一个原型链,且最顶端是Object.prototype这个预定义的对象。 原型链的取值是类似这样:Base.prototype,Object.prototype。虽然这些取值都是对象,我们可以看成当前对象的一个继承层次。Instanceof 操作符就用于判断这种继承层次。 如: d  Instanceof Base 会逐层查找d的原型链的取值,若存在Base.prototype则返回true,否则返回false。

  因为原型链上的对象的所有属性和方法都会被“继承”至当前对象, 当我们在原型链上找到Base.prototype时,我们认为当前对象继承了Base“类”。 其实,当前对象只是拥有了Base这个函数对象的prototype属性所指向的普通对象的所有属性和方法,但并不具备new Base() 对象的所有属性和方法。因为new Base()对象在构建时,除了_proto_=Base.prototype获得的属性方法以外,还通过其构造函数体增加了其它一些而外的属性和方法。  

 

Property Lookup

 

    因为js对象是属性-值对的集合,我们获取某个属性(方法)的时候,js引擎会沿着原型链:__proto__.__proto__.__proto__寻找,比如有个object叫xxx,我们执行alert(xxx.a),也就是读取xxx的a属性,那么JS首先会到xxx本身去找a属性,如果没找到,则到xxx.__proto__里去找a属性,由此沿着原型链往上,找到即返回(没找到,则返回undefined)。

 

 

 

附注: 关于默认原型链(原型链可以通过手工在各个普通对象之间指定来实现继承)。

    普通对象是由函数对象创建的,函数对象是由new Function()创建的, Function本身是一个函数对象。所有普通对象包含一个_proto_指向函数对象的prototype属性。 通过new Function()创建函数对象时,该函数对象的prototype属性会被赋值为普通对象(其_proto_属性指向Object.prototype,该对象的_proto_为null。),该函数对象的_proto_指向Function.prototype.而Function这个函数对象是一个函数对象,在new 该函数对象的时候,其_proto_会指向Function.prototype,其prototype(即:Function.prototype)会指向一个普通对象(其_proto_属性指向Object.prototype,该对象的_proto_为null。) 也就是说,Function这个预定义的函数对象的_proto_和prototype这两个属性都指向一个普通的对象。