对象、原型、原型链、继承

一、对象

  1. 对象(object)是某一个类(class)的实例(instance)
  • 类可以理解成模具
  • 对象可以理解成模具开发的产品
  • 对象的另一个特性就是封装:把细节隐藏掉,想要修改对象的属性需要通过它提供的方法去访问
        //用一个构造函数Fn生成了一个对象p; 对象p继承自构造函数Fn()
        function Fn(){
            console.log('name:Ceaser');
        }
        //通过类Fn(),生成属于这个类型的对象p
        //一个函数通过new操作符,可以让一个函数作为构造函数生成一个对象
        var p = new Fn();
        typeof p;  //object
        //所以这个对象p就是这个类的实例
        p instanceof Fn;  //true p是Fn的实例
        //p1和p2作为两个不同的新实例(创建了不同的副本),对类(属性的值)做修改互不影响
        function Fn(){
            this.name = 'hunger';
            this.age = 18;
        }

        var p1 = new Fn();
        var p2 = new Fn();
        p1.name = 'velley';
        console.log(p2);  //hunger 
        //根据参数需要把参数设置为变量
        function Fn(name, age){
            this.name = name;
            this.age = age;
        }

        var p1 = new Fn('hunger', 21);
        var p2 = new Fn('velley', 14);
        //调用对象的方法
        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

二、原型

  • 构造函数Person中存在属性prototype,属性prototype指向原型对象Prototype
    原型对象Propotype包括:构造器constructor(指向构造函数Person) 和 原型属性_ proto_ 以及 自己定义的方法或属性,
    当通过new方法创建构造函数Person的实例后得到对象p1,实例的_ proto_指向它的创造者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访问属性时先从继承来的在构造函数Person的属性中查找,查找不到时再从构造函数Person的原型对象Prototype中查找


    原型链
  • 调用p2.name,对象实例p2没有name属性,此时要从原型上查找。得到hello
    原型链
  • 深入:

_ proto_指向构造它的函数的原型对象,prototype指向它自身的函数的原型对象

任何对象都是被创建出来的,对象内部都存在原型属性_proto_,_proto_保存着构造它的原型对象
对象Person里面有属性prototype,证明Person本身是一个对象(函数也是一种对象),所以对象Person内部也存在原型属性_proto_
原型对象Prototype也存在属性_proto_

Object在JS中本身是一个函数function(){ [native code] }new Object才是创建一个对象Object{}
任何对象都是由Object函数创建的(即new Object方式)
Object.prototype === Person.prototype._proto_返回true证明原型对象Prototype的创建者是Object。因为原型对象Prototype的原型属性_ proto_指向Object的原型对象Prototype
由此证明:原型对象Prototype的创建者是构造函数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__属性
任何一个函数都拥有prototype,任何一个对象都拥有_ proto_
函数中的prototype是创建时就有的
对象中的_ proto_是对象的创造者(即构造函数中的prototype)
因为对象都是由Object函数创建的,所以对象的属性_ proto_指向函数的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);
        }

        //在函数MilkCake的作用域里执行Cake函数(此时MilkCake取得了Cake的属性)
        function MilkCake(name, size, taste){
            console.log(this);
            Cake.apply(this, [name, size]);
            this.taste = taste;
        }

        //创建一个Cake的对象实例指向 MilkCake的原型对象(此时MilkCake继承了Cake的属性及原型对象)
        MilkCake.prototype = new Cake();
        //将MilkCake原型对象的构造器指向MilkCake函数
        MilkCake.prototype.constructor = MilkCake;

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

constructor返回创建实例对象的构造函数的引用,所有对象都会从它的原型对象上继承一个constructor属性

image.png

image.png

  • 继承原型函数方法(Es5简便方法)
        function inherit(superType, subType){
            //拷贝一份父函数的原型对象
            var _prototype =  Object.create(superType.prototype);
            //将拷贝原型对象的构造器指向子函数
            _prototype.constructor = subType;
            //将拷贝的原型对象指向子函数的prototype属性
            subType.prototype = _prototype;
        }
        inherit(superType, subType);
image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容