js之面向对象(原型链、重定向、重写new)

一.原型原型链

  1. 所有的类都是函数数据类型的(包含内置类)
    所有的函数都天生自带一个属性:prototype原型
    prototype的属性值默认是一个对象数据类型值【堆】
    在对象中存储的是供实例能调用的公共属性和方法
    并且在类的原型对象上,默认有一个属性constructor构造函数,属性值是当前类本身
  2. 所有对象数据类型值也天生自带一个属性:__proto__原型链
    __proto__属性的属性值:当前实例所属类的原型prototype.实例.proto===类.prototype
    都哪些值是对象数据类型的:
    普通对象/数组对象/正则对象/日期对象/类数组对象/DOM对象…
    大部分实例(除基本数据类型外)也是对象类型
    类的原型prototype也是对象类型的
    函数也是对象“函数的三种角色”
    …万物皆对象,所有的值都是对象类型的
  3. Object是所有对象数据类型的“基类”,Object.prototype.__proto__如果要指向也是指向Object.prototype也就是自己,这样没有意义,所以Object.prototype.__proto__等于null.
    <script>
        function Fn(){
            this.x=100;
            this.y=200;
            this.getX=function (){
                console.log(this.x);
            }
        }
        Fn.prototype.getX=function(){
            console.log(this.x);
        };
        Fn.prototype.getY=function(){
            console.log(this.y);
        };
        let f1=new Fn;
        let f2=new Fn;
        console.log(f1.getX===f2.getX);     //f
        console.log(f1.getY===f2.getY);     //t
        console.log(f1.__proto__.getY===Fn.prototype.getY);   //t
        console.log(f1.__proto__.getX===f2.getX);          //f
        console.log(f1.getX===Fn.prototype.getX);          //f
        console.log(f1.constructor);           //Fn函数
        console.log(Fn.prototype.__proto__.constructor);    //Object
        f1.getX();     //100
        f1.__proto__.getX();   //undefined
        f2.getY();       //200
        Fn.prototype.getY();     //undefined
    </script>

在这里插入图片描述
二.重定向
原型重定向,为了方便批量给原型上扩充属性和方法,但是新定向的对象上没有constructor属性,结构不完整;浏览器默认生成的原型对象因为缺少引用会被释放掉,可能导致原始加入的属性和方法丢失掉。
内置类的原型是不允许重定向的,怕把内置的方法整没了。

    <script>
        function fun(){
            this.a=0;
            this.b=function(){
                alert(this.a);
            }
        }
        fun.prototype={
            b:function(){
                this.a=20;
                alert(this.a);
            },
            c:function(){
                this.a=30;
                alert(this.a)
            }
        }
        var my_fun=new fun();
        my_fun.b();  //'0'
        my_fun.c();  //'30'
    </script>

在这里插入图片描述

    <script>
        function Fn(){
            this.x=100;
            this.y=200;
        }
        //原始原型对象
        Fn.prototype.getX=function (){};
        //重定向的新对象 :没有constructor,也没有getX了...
        Fn.prototype={
            getY:function(){}
        };
        let f1=new Fn();

原始原型对象上如果不存在其他属性方法,我们只需要把constructor手动设置一下即可,如下:

        Fn.prototype={
            constructor:Fn,
            getX(){},
            getY(){},
            getZ(){}
        }

重定向之前,最好拿新原型对象和原始的原型对象合并一下
Object.assign(对象1,对象2):合并两个对象,重复的属性以对象2 为主,如下所示:

    <script>
        function Fn(){
            this.x=10;
            this.y=20;
        }
        Fn.prototype.z=300;
        Fn.prototype=Object.assign(Fn.prototype,{
            getX(){},
            getY(){},
            getZ(){}
        });
    </script>

三.重写内置new

  1. new Dog(…)
    (1)创建一个Dog类的实例对象
    对象(空)
    对象.proto===Dog.prototype
    (2)把Dog当作普通函数执行:私有上下文/作用域链/形参赋值/变量提升/代码执行…
    (3)方法中的this指向创建的实例对象
    (4)看方法的返回结果,如果没有return或者返回的是基本类型值,则返回的都是实例对象,否则以函数返回值为主。
  2. Object.create([对象A]):创建一个空对象,并且把对象A作为他的原型。 空对象.proto===对象A
    实例:
    <script>
        function Dog(name){
            tis.name=name;
        }
        Dog.prototype.bark=function (){
            console.log('wangwang');
        }
        Dog.prototype.sayName=function(){
            console.log('my name is'+this.name);
        }
        //Func[function]:想创造哪个类的实例,就传递这个类
        //params[array]:基于剩余运算符获取其余传递的实参,这些值都是给类传递的实参
        function _new(Func){
            //创建一个实例对象
            let obj=Object.create(Func.prototype);
            //把类当作普通函数执行:基于call方法强制改变上下文中的this是创建的实例对象obj
            let result=Func.call(obj,...params);
            if(result!==null && /^(object|function)$/i.test(typeof result)) return result;
            return obj;
        }
        let sanmao=_new(Dog,'三毛');
        sanmao.bark();
        sanmao.sayName();
        console.log(sanmao instanceof Dog);  //true
    </script>
  1. Object.create如何实现
    Object.create是ES2015(不是ES5,是ES6前身)提供的方法,不兼容低版本浏览器
        Object.create=function create(obj){
            if(obj===null||typeof obj!=="object"){
                throw new TypeError('Object prototype may only be an Object');
            }
            function Anoymous(){}
            Anoymous.prototype=obj;
            return new Anoymous;
        }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值