對象、原型、原型鏈、繼承

一、對象

  1. 對象(object)是某一個類(class)的實例(instance)
  • 類可以理解成模具
  • 對象可以理解成模具開發(fā)的產(chǎn)品
  • 對象的另一個特性就是封裝:把細節(jié)隱藏掉,想要修改對象的屬性需要通過它提供的方法去訪問
        //用一個構造函數(shù)Fn生成了一個對象p; 對象p繼承自構造函數(shù)Fn()
        function Fn(){
            console.log('name:Ceaser');
        }
        //通過類Fn(),生成屬于這個類型的對象p
        //一個函數(shù)通過new操作符,可以讓一個函數(shù)作為構造函數(shù)生成一個對象
        var p = new Fn();
        typeof p;  //object
        //所以這個對象p就是這個類的實例
        p instanceof Fn;  //true p是Fn的實例
        //p1和p2作為兩個不同的新實例(創(chuàng)建了不同的副本),對類(屬性的值)做修改互不影響
        function Fn(){
            this.name = 'hunger';
            this.age = 18;
        }

        var p1 = new Fn();
        var p2 = new Fn();
        p1.name = 'velley';
        console.log(p2);  //hunger 
        //根據(jù)參數(shù)需要把參數(shù)設置為變量
        function Fn(name, age){
            this.name = name;
            this.age = age;
        }

        var p1 = new Fn('hunger', 21);
        var p2 = new Fn('velley', 14);
        //調(diào)用對象的方法
        function Fn(name, age){
            this.name = name;
            this.age = age;
            this.say = function(){
                console.log(this.name + '說: 我' + this.age + '歲了。');
            }
        }

        var p1 = new Fn('hunger', 21);
        var p2 = new Fn('velley', 14);
        p1.say();  //hunger說: 我21歲了。
        p2.say();  //velley說: 我14歲了。
        //注意:不使用new,p1為undefined  28.24-31.05
        function Fn(name, age){
            this.name = name;
            this.age = age;
            this.say = function(){
                console.log(this.name + '說: 我' + this.age + '歲了。');
            }
        }

        var p1 = Fn('hunger', 21);
        var p2 = new Fn('velley', 14);
        console.log(p1);  //undefined

二、原型

  • 構造函數(shù)Person中存在屬性prototype,屬性prototype指向原型對象Prototype
    原型對象Propotype包括:構造器constructor(指向構造函數(shù)Person) 和 原型屬性_ proto_ 以及 自己定義的方法或?qū)傩裕?br> 當通過new方法創(chuàng)建構造函數(shù)Person的實例后得到對象p1,實例的_ proto_指向它的創(chuàng)造者Person的整個原型Propotype
    此時對象p1包括:name:hunger、age:21、以及繼承自p1的原型屬性_ proto_
        function Person(name, age){
            this.name = name;
            this.age = age;
            this.say = function(){
                console.log(this.name + '說: 我' + this.age + '歲了。');
            }
        }

        var p1 = new Person('hunger', 21);
  • 原型對象是對象實例的公共空間。
    可以通過對象實例訪問保存再原型對象中的值,但不能通過對象實例重寫原型中的值
        function Person(name, age) {
            this.name = name;
            this.age = age;
            this.say = function () {
                console.log(this.name + '說: 我' + this.age + '歲了。');
            }
        }
        Person.prototype = {
            friend: 'Cherry'
        }

        var p1 = new Person('hunger', 21);
        p1.friend = 'Neco';
        console.log(p1.friend);  //Neco

        var p2 = new Person('Danee', 22);
        console.log(p2.friend);  //Cherry
Person對象的_proto_ 與 Prototype原型對象的_proto_ 指向Object對象
原型

三、原型鏈

  • 對象實例p1訪問屬性時先從繼承來的在構造函數(shù)Person的屬性中查找,查找不到時再從構造函數(shù)Person的原型對象Prototype中查找


    原型鏈
  • 調(diào)用p2.name,對象實例p2沒有name屬性,此時要從原型上查找。得到hello
    原型鏈
  • 深入:

_ proto_指向構造它的函數(shù)的原型對象,prototype指向它自身的函數(shù)的原型對象

任何對象都是被創(chuàng)建出來的,對象內(nèi)部都存在原型屬性_proto_,_proto_保存著構造它的原型對象
對象Person里面有屬性prototype,證明Person本身是一個對象(函數(shù)也是一種對象),所以對象Person內(nèi)部也存在原型屬性_proto_
原型對象Prototype也存在屬性_proto_

Object在JS中本身是一個函數(shù)function(){ [native code] },new Object才是創(chuàng)建一個對象Object{}
任何對象都是由Object函數(shù)創(chuàng)建的(即new Object方式)
Object.prototype === Person.prototype._proto_返回true證明原型對象Prototype的創(chuàng)建者是Object。因為原型對象Prototype的原型屬性_ proto_指向Object的原型對象Prototype
由此證明:原型對象Prototype的創(chuàng)建者是構造函數(shù)Object

        function Person(name) {
            this.name = name;
        }
        Person.prototype = {
            sayName: function(){
                console.log('My name is: ' + this.name);
            }
        }

        var p1 = new Person('hunger');
        var p2 = new Person('danee');
        p1.sayName();

image.png

原型對象只有一個 [[prototype]] 正常的是隱藏的 訪問不到,瀏覽器為了讓你訪問到,弄了個__proto__屬性
任何一個函數(shù)都擁有prototype,任何一個對象都擁有_ proto_
函數(shù)中的prototype是創(chuàng)建時就有的
對象中的_ proto_是對象的創(chuàng)造者(即構造函數(shù)中的prototype)
因為對象都是由Object函數(shù)創(chuàng)建的,所以對象的屬性_ proto_指向函數(shù)的prototype
上例:
Person.prototype.__proto__ === Object.prototype
p1.__proto__ === Person.prototype
image.png

image.png

原型鏈

四、基本包裝類型

        var str = 'hellow';
        等同于
        var str = new String('hellow');
基本包裝類型

image.png

四、繼承

        function Cake(name, size){
            console.log(this);
            this.name = name;
            this.size = size;
        }
        Cake.prototype.sayName = function(){
            console.log('I am :' + this.name);
        }
        Cake.prototype.saySize = function(){
            console.log('My size is' + this.size);
        }

        //在函數(shù)MilkCake的作用域里執(zhí)行Cake函數(shù)(此時MilkCake取得了Cake的屬性)
        function MilkCake(name, size, taste){
            console.log(this);
            Cake.apply(this, [name, size]);
            this.taste = taste;
        }

        //創(chuàng)建一個Cake的對象實例指向 MilkCake的原型對象(此時MilkCake繼承了Cake的屬性及原型對象)
        MilkCake.prototype = new Cake();
        //將MilkCake原型對象的構造器指向MilkCake函數(shù)
        MilkCake.prototype.constructor = MilkCake;

        var Cake1 = new MilkCake('牛奶蛋糕', 16, '甜');
        console.log(Cake1);

constructor返回創(chuàng)建實例對象的構造函數(shù)的引用,所有對象都會從它的原型對象上繼承一個constructor屬性

image.png

image.png

  • 繼承原型函數(shù)方法(Es5簡便方法)
        function inherit(superType, subType){
            //拷貝一份父函數(shù)的原型對象
            var _prototype =  Object.create(superType.prototype);
            //將拷貝原型對象的構造器指向子函數(shù)
            _prototype.constructor = subType;
            //將拷貝的原型對象指向子函數(shù)的prototype屬性
            subType.prototype = _prototype;
        }
        inherit(superType, subType);
image.png
最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容