Javascript 对象原型& 原型链

JS 对象原型和原型对象

JS构造函数创建对象的缺陷

instance Javascript 对象原型& 原型链_第1张图片

上面的例子中 console.log(ldh.sing === zxy.sing);为false , 对于相同的方法,存储的地址不同

  • 构造函数存在严重的内存浪费,如果想要所有的对象使用同一个函数需要使用到prototype. JS规定,每个函数都有一个prototype属性,指向另一个对象。构造函数的prototype对象比较特殊,我们通常讲的prototype就是指构造函数的prototype我们可以把那些不变的方法,直接定义在prototype对象上 这样所有的对象实例就可以共享这些方法
  • prototype 是一个静态成员 可以看到下面例子中的Star.prototype.sing(ldh.username);是undefined sing . 静态中成员的this 没有意义。

Javascript 对象原型& 原型链_第2张图片

instance

   <script>
        function Star(username, age) {
     
            this.username = username;
            this.age = age;
            /* this.sing = function () {
                console.log(this.username + ' sing');
            } */

        }
        //static member
        Star.gender = 'male';
        console.log(Star.gender);
        //prototype
        Star.prototype.sing = function () {
     
            console.log(this.username + ' sing');
        }

        //instance 
        var ldh = new Star('liu', 60);
        var zxy = new Star('zhang', 60);
        console.log(Star.prototype.sing === ldh.sing);
        console.log(ldh.sing === zxy.sing);
        Star.prototype.sing(ldh.username);
        ldh.sing();
    </script>
  • 结果如下:
    Javascript 对象原型& 原型链_第3张图片

为什么在prototype中定义的函数可以在实例中直接调用?

接上面的例子,在prototype中添加的sing ,可以使用ldh.sing调用呢?
我分别打印了ldh 实例和Star构造函数的属性,可以看到实例中的__proto__和prototype 相同

  • proto 称为对象原型,指向原型对象 prototype ldh.proto===Star.prototype为True
  • 不同的是 对象原型 是实例成员而原型对象是静态成员
  • 对象原型(proto)的作用是为对象的查找机制提供了一个方向,但是它本身是一个非标准属性,在实际开发中,不可以使用这个属性

原型对象的constructor

从上面的分析可以知道 所有的对象原型(proto)都是指向prototype的。而prototype中的constructor是构造函数本身(看图)

当我们需要在prototype中添加多个公用方法,而给prototype赋值时 需要重新给constructor 赋值。表明创建对象的构造函数

 //覆盖prototype 并重置构造函数
        Star.prototype = {
     
            constructor: Star,
            sing: function () {
     
                console.log('sing');
            },
            moive: function () {
     
                console.log('moive');
            }
        }
        var ldh = new Star('liu', 60);
        console.log(Star.prototype);
        console.log(ldh.__proto__);

原型链

按照上面的实例,我们可以推导出下面的原型链 Javascript 对象原型& 原型链_第4张图片
JS中对象成员的查找是沿着原型链依次向上的,知道object为止

拓展方法

我们可以操作已有类型的prototype 来拓展已有类型的方法
以数组类型为例:

<script>
        Array.prototype.sum = function () {
     
            var sum = 0;
            for (let i = 0; i < this.length; i++) {
     
                sum += this[i];
            }
            return sum;
        }
        var arr = [2, 3, 4, 5];
        console.log(arr.sum());

    </script>

结论

实验和查资料,得出结论

  • 所有的JavaScript 对象都有__proto__(对象的原型),指向构造函数的原型对(prototype)
  • 所有原型对象都有一个constructor属性,指向其构造函数,所以这里是一个环,构造函数又有一个prototype属性来指向其对象原型。
  • 构造函数中都有原型对象(prototype)的静态成员,来共享属性和方法给构造函数的实例。
  • 所有的函数都有prototype 这句话值得商榷,built-in类型的函数就没有

Javascript 对象原型& 原型链_第5张图片
为什么内置对象的函数没有prototype?
看StackOverflow 的文章https://stackoverflow.com/questions/14169384/why-do-built-in-functions-not-have-a-prototype-propertybuilt-in 没有prototype

你可能感兴趣的:(笔记,javascript,js,prototype,class)