web(原型链与继承)

一、 原型链

  _proto_ : 原型链,对象的属性,指向生成该对象的构造函数的原型对象
 prototype: 原型对象,函数(构造函数)特有的属性,存储共享的属性和方法

 // 所有的javascript对象都会继承一个prototype原型对象  继承原型对象上的属性和方法
 // Date  对象  从Date.prototype 原型对象上继承属性和方法
 // Array 对象  从Array.prototype  原型对象上继承属性和方法

以js数组对象Array为例:

    var arr = new Array();
    console.log(typeof Array);
    //输出function,即Array本质是一个函数,js中函数也是对象
    
    console.log(arr.__proto__);
     //输出的是Array(arr的上一层,即创建arr的构造函数)的原型对象
     
    console.log(arr.__proto__.__proto__);
    //输出的是Object(即Array的上一层)的原型对象
    
    console.log(arr.__proto__.__proto__.__proto__);
    //输出为null  Object为最高层  没有继承任何对象

原型链与圆形函数的关系,通过下面的例子作以说明

    //定义一个Person 父类
    function Person() {
        this.color = "";
        this.sleep = function () {
        }
    }
    
    //给Person类添加原型对象
    Person.prototype = {
        constructor: Person,
        name: "",
        sex: "",
        eat: function () {
           return "eat";
        }
    }
    
     //定义一个子类Child
     function Child() {
        this.job = "";
    }
  
    // 子类  原型继承 父类
    Child.prototype = new Person();  //先继承,操作子类构造函数的prototype属性
    var c = new Child();             //再实例化子类对象
    
    console.log(c.__proto__);          //输出父类
    console.log(c.__proto__.__proto__);//输出父类的原型对象
    console.log(c.__proto__.__proto__.__proto__);          //输出Object 原型对象
    console.log(c.__proto__.__proto__.__proto__.__proto__);//输出null

 /*下面这种继承没有意义,之前自己在练习过程中上下两种输出一致,对此理解有误,之后发现了问题*/
 /*×××该方法请勿采用×××*/
    var c1=new Child();          //先实例化对象
    c1.__proto__=new Person();   //再继承,操作子类实例化对象的"__proto__"对象
    
    console.log(c1.__proto__);          //输出父类
    console.log(c1.__proto__.__proto__);//输出父类的原型对象
    console.log(c1.__proto__.__proto__.__proto__);         //输出Object 原型对象
    console.log(c1.__proto__.__proto__.__proto__.__proto__);//输出null

    /*两个实例化对象以上的输出一致*/
    
    console.log(Child.prototype == c.__proto__);  //输出true
    /* 第一种实例化:
    *  Child的prototype  通过 Child.prototype = new Person()   设置为了 Person
    *  因此Child实例化后的对象的__proto__也为person
    */
    
     console.log(Child.prototype == c1.__proto__);  //输出false
     /*第二种实例化:
     *先实例化后再继承,只对实例化后的c1对象进行了 c1.__proto__=new Person()的操作  
     *因此,Child的prototype未曾设置,c1的__proto__为person;
     */
     

总结:
prototype为函数特有的,__proto__是对象的属性
构造方法. prototype== 实例对象.__proto__

二、继承

  1. 原型链继承:将父类的实例化对象赋给子类的原型对象
    //原型链继承

    //定义一个父类
    function Person(name,age){
        this.name=name;
        this.age=age;
        this.eat=function(){
            return this.name+"吃饭";
        }
    }
    //为父类增添原型属性
    Person.prototype.color="黄种人";
    //为父类增添原型属性方法
    Person.prototype.sleep=function(){
        return this.name+"睡觉";
    };
    //定义一个子类
    function Child(sex){
      this.sex=sex;
        this.drink=function(){
            return this.name+"喝水";
        }
    }
    //将父类Person的实例化对象 赋给子类Child的原型对象prototype
    Child.prototype=new Person("张三","20");
    //实例化子类对象
    var child = new Child("男");
    //输出自身、父类、父类原型所有的属性及方法
    console.log(child);

    //判断child对象是否为构造类Child Person的实例化对象
    console.log(child instanceof Child);  //true
    console.log(child instanceof Person);   //true

优点:
1.实例即是子类的实例,也是父类的实例
2.子类本身,父类本身,父类原型,父类原型新增的所有属性方法,子类都可以访问到
缺点:
1.子类实例无法直接向父类构造方法传参;
2.继承之后原型对象上的属性全部是共享的
3.不能多继承 ,即一个子类不能继承多个父类

2.构造继承:通过call apply将父类属性及方法完全复制给子类

//定义父类Person
    function Person(name,sex){
        this.name=name;
        this.sex=sex;
        this.eat=function(){
            return this.name+"吃饭";
        }
    }
    //定义父类 Country
    function Country(con){
        this.con=con;
    }
    //添加父类原型属性
    Country.prototype.fn="父类原型";  //子类不能继承
    //定义子类
    function Child(age,n,s,c){
        this.age=age;
        Person.apply(this,[n,s]);    //继承Person父类
        Country.call(this,c);        //继承Country父类
    }

    var child=new Child(20,"张三","男","China");
    console.log(child);

    console.log(child instanceof  Child);  //true
    console.log(child instanceof Person);  //false
    console.log(child instanceof  Country); //false

优点:
1.可以多继承
2.子类实例可向父类构造函数传参
缺点:
1.构造继承只能call apply
2.子类只能继承 父类的构造属性和方法,不能继承父类原型的属性和方法
3.实例对象只是子类的实例,不是父类的实例

补充:call() 与 apply()方法

每个函数都包含两个非继承而来的方法:call()apply()
两方法作用均为:改变函数体内部 this 的指向

call(thisObj,参数1,参数2...);
apply(thisObj,[参数1,参数2...]);

3.实例继承:在子类里直接实例化父类(子类的实例返回 给父类添加的属性和方法)

 function Person(name,sex){
        this.name=name;
        this.sex=sex;
        this.eat=function(){
            return this.name+"吃饭";
        }
    }
    Person.prototype.fn="父类原型";  //子类不能继承

    function Child(n,s){
       var child=new Person(n,s);  //子类内部实例化父类
        return child;
    }

    var child=new Child("张三","男");
    console.log(child);   直接输出实例化后的Person对象

    console.log(child instanceof  Child);  //false
    console.log(child instanceof  Person);  //true

优点:
1.可以传递给父类参数
2.不限制调用的方式
缺点:
1.不能多继承
2.实例是父类的实例,不是子类的实例

4.拷贝继承:将父类对象中的每个属性和方法遍历复制到子类的原型中

 //父类Person
    function Person(name){
        this.name=name;
        this.eat=function(){
            return this.name+"吃饭";
        }
    }

    //父类Country
    function Country(con){
        this.con=con;
    }
    function Child(age,n,c){
        this.age=age;
        var per=new Person(n);
        var per1=new Country(c);
        for(var p in per){
            Child.prototype[p]=per[p];  //将父类实例的属性和方法复制给资料类的原型
        }
        for(var key in per1){
            Child.prototype[key]=per1[key];
        }
    }

    var child=new Child(20,"张三","china");
    console.log(child);
    console.log(child instanceof  Child);  //true
    console.log(child instanceof  Person);  //false
    console.log(child instanceof  Country);  //false

实例是子类的实例,不是父类的实例
优点:
1.可以多继承
2.子类可以向父类传递参数
缺点:
1.效率较低,内存占用高

5.组合继承:原型链继承+构造继承

//父类Person
    function Person(name) {
        this.name = name;
        this.sleep = function () {
            return this.name + "睡觉";
        }
    }

    //父类 Country
    function Country(con){
        this.con=con;
    }
    function Child(sex,n,c){
        this.sex=sex;
        Person.call(this,n);  //可多继承
        Country.call(this,c);
    }

    Child.prototype=new Person();

    //可直接向父类传参,弥补了原型链继承的缺点
    var child = new Child("男","张三","China");
    console.log(child);
    console.log(child instanceof  Child);  //true
    console.log(child instanceof  Person);  //true
    console.log(child instanceof  Country);  
    // 子类没有通过原型链继承Country  false

优点:
1.实例可以直接向父类传参
2.没有原型对象属性的共享
3.可多继承
4.实例是子类的,也是父类的
缺点:
调用了两次父类的构造函数

6.寄生组合继承:将父类的原型给予一个空对象的原型

//父类
    function Person(name) {
        this.name = name;
        this.sleep = function () {
            return this.name + "睡觉";
        }
    }
  //子类
    function Child(n, age) {
        this.age = age;
        this.eat = function () {
            return this.name + "吃饭"
        }
        Person.call(this,n);
    }

    //寄生
    (function(){
        var fn=function(){
        };
        //将父类的原型对象给予空对象
        //避免两次调用父类的构造函数
        fn.prototype=Person.prototype;
        Child.prototype=new fn();
    })();

    var child=new Child("张三",20);
    console.log(child);

    console.log(child instanceof Child); //true
    console.log(child instanceof Person);//true

优点:
处理了组合继承的缺点 ,避免两次调用父类的构造函数
实例是子类的,也是父类的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Node.js中,原型链污染是一种特殊的攻击技术,它利用JavaScript的原型继承机制来修改对象的原型链并注入恶意代码。通过修改对象的原型链,攻击者可以影响对象的行为并执行恶意操作。 实现原型链污染的过程如下: 1. 攻击者首先要找到一个合适的目标对象,该对象通常是在代码中被使用的,并且具有对外部输入进行处理的功能。 2. 攻击者通过修改目标对象的原型链,向其原型对象中添加恶意代码或属性。这通常是通过修改被攻击对象的__proto__属性来实现的。 3. 当目标对象在后续的代码中被使用时,恶意代码或属性将会被执行或访问。 例如,在Node.js中,如果一个Web应用程序使用了一个处理JSON数据的库,并且对外部的JSON数据没有进行充分的验证和过滤,那么攻击者可以通过构造恶意的JSON数据来实现原型链污染。攻击者可以将恶意代码添加到JSON数据中的__proto__属性,当应用程序解析并使用该JSON数据时,恶意代码将被执行。 总结起来,Node.js的原型链污染是一种利用JavaScript的原型继承机制来修改对象的原型链并注入恶意代码的攻击技术。攻击者可以通过修改目标对象的__proto__属性来实现原型链污染,并在后续的代码中执行恶意操作。因此,在开发过程中,需要注意对外部输入的验证和过滤,以防止原型链污染攻击的发生。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值