`

prototype constructor __proto__释疑

 
阅读更多
经典例子分析

    function Person(name) {
        this.name = name;
    };
    Person.prototype.getName = function() {
        return this.name;
    };
   
    /*

        以下语句的实际运行过程是:
        第一步,建立一个新对象(叫p吧);
        第二步,将该对象(p)内置的原型对象(即__proto__属性指向的对象)设置为构造函数(就是

        Person)的prototype 属性引用的那个原型对象;即p.__proto__ = Person.prototype
        第三步,将该对象(p)作为this 参数调用构造函数(就是Person),完成成员设置等初始化工作。   
    */
    var p = new Person("ZhangSan");


    //若以以下两句代替上面那句,则不能执行p.getName()
    //var p = {};
    //Person.call(p);

    console.log(Person.prototype.constructor === Person); // true

   /*

     p本身没有constructor属性,但p的__proto__指向Person.prototype,所以实际上p.constructor 调用的是

     Person.prototype.constructor    

   */
    console.log(p.constructor === Person);  // true
   

   附:Person.constructor 不等于 Person.prototype.constructor

   javasciprt的类概念是假的类概念,试图以prototype表示对象原型(即类),但事实上new出来的实例是与类通过共用同一个原型对象达到模板的效果,在此基础上同时限定了修改对象的属性并不会直接修改到原型对象,而修改原型对象的属性作用到每个对象上,从而保证了由类创建对象(即类->对象)的要义效果。
--------------------------------------------------------------------------------------------------------------------

 

constructor例子分析
    1. function A(){
            var s = "mianqiang";
        }
        function B(){}
        var a = new A();
        A.prototype.constructor = B;
        alert(a.constructor);//输出的是B函数
       
    2. function A(){
            var s = "mianqiang";
        }
        function B(){}
        var a = new A();
        a.constructor = B;//这种情况下constructor只是作为a的一个普通属性值
        alert(a.constructor);//输出的是B函数
        alert(A.prototype.constructor);//输出的是A函数(重点)
       
    3. function A(){
            var s = "mianqiang";
        }
        function B(){ }
        function C(){}
        var a = new A();
        a.constructor = B;
        A.prototype.constructor = C;
        alert(a.constructor);//输出B
        alert(A.prototype.constructor);    //输出C


    4. function a(){
        this.cc = function(){alert("ac")};
    }
    a.prototype.bb = function(){
        alert("aa");
    }

    function b(){
        //mark 1: this.cc = function(){alert("bc")};
    }
    b.prototype.bb = function(){
        alert("bb");
    }
   
    /*

     下面语句将b的constructor转成函数a。此例子在于说明constructor的影响很小,更改成a并不会引起

     new b()会采用a去构造对象(重点)

     mark 2:

   */
    b.prototype.constructor = a;  

    //mark 3: b.prototype = a.prototype;

    var z1 = new b();
    z1.bb();    //bb,若注释mark 2,去掉mark 3注释,则显示aa,但下面的z1,.cc()仍是报undefined
    //z1.cc is not a function(cc为undefined) ,如果把mark 1处的注释去掉,则输出“bc”
    z1.cc();


--------------------------------------------------------------------------------------------------------------------

 

prototype的作用范围
1.    function A(){}
    A.prototype.pa = 10;
    var a1 = new A();
    alert(a1.pa);//10
    a1.pa = 50;
    var a2 = new A();
    alert(a2.pa);//10

2.    function A(){}
    A.prototype = {pa:10};
    var a1 = new A();
    alert(a1.pa);//10
    a1.pa = 50;
    var a2 = new A();
    alert(a2.pa);//10

3.    function A(){}
    A.prototype.ca = {pa:10};
    var a1 = new A();
    alert(a1.ca.pa);//10
    //a1.ca = {};
    a1.ca.pa = 50;

    /*
     a1为实例,a1实例没有ca属性,所以a1.ca.pa这样的路径是直接影响在prototype的ca里的pa属性上;
     如果a1有ca属性(参看上面的注释句),则不会影响到prototype的ca里的pa属性上,
     而是影响在a1实例的ca对象的pa属性上,这种情况下最后a2.ca.pa输出的值则是10而不是50

     这种修改一个对象实例的属性从而影响到类的原型属性是个错误的用法,打破了JavaScript试图表达类概念的意图,同时也显示JavaScript的类概念是伪类
    */
    var a2 = new A();
    alert(a2.ca.pa);//50

4.    function A(){}
    A.prototype.ca = {pa:10};
    var a1 = new A();
    alert(a1.ca.pa);//10
    a1.ca = {ht:20};
    var a2 = new A();
    alert(a2.ca.pa);//10

5.    function A(){}
    A.prototype.ca = {pa:10};
    var a1 = new A();
    alert(a1.ca.pa);//10
    a1.ca = {ht:20};
    var a2 = new A();
    alert(a2.ca.ht);//undefined

总结:假设:实例inst本身没有属性a,但inst所属函数Func的prototype有属性a。执行console.log(inst.a),会去读取Func的prototype上的属性a;若执行语句inst.a=10,则视为为实例本身添加a这个属性并且赋值为10,而非修改了Funcprototype上的a属性值。


--------------------------------------------------------------------------------------------------------------------

 

其他

  • 任何函数对象都有prototype属性,prototype属性通常为"object"类型,除了 Function.prototype,它   为"function"类型,虽然Function.prototype是一个函数对象,但Function.prototype.prototype为 undefined;普通对象没有prototype属性;
  • 对象都有__proto__属性。Object.prototype.__proto__ 为 null。

function func(){}
alert(typeof func.prototype);//output : "object"; 注意这里的"object"的"o"是小写的
alert(typeof null);//output: "object"

 

alert(typeof Object);//output: "function"
alert(typeof Number);//output: "function"
alert(typeof Function);//output: "function"

 

继承:

function Person(name, age) {
        this.name = name,
        this.age = age
    }
    Person.prototype.setAge = function () {
        console.log("111")
    }
    function Student(name, age, price) {
        Person.call(this, name, age)
        this.price = price
        this.setScore = function () {}
    }
    Student.prototype = Object.create(Person.prototype)//核心代码
    Student.prototype.constructor = Student//核心代码
    var s1 = new Student('Tom', 20, 15000)
    console.log(s1 instanceof Student, s1 instanceof Person) // true true
    console.log(s1.constructor) //Student
    console.log(s1)

 

参考:

深入了解javascript中的prototype与继承

Js中Prototype、__proto__、Constructor、Object、Function关系介绍

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics