类与对象以及原型机制

本文介绍了JavaScript中类的概念,如何通过构造函数和继承实现子类对父类属性和方法的继承,以及如何利用原型避免内存浪费。重点讲解了类的使用、原型链和扩展内置对象的方法,适合理解面向对象编程进阶者阅读。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

抽取对象共用的属性和行为封装成类

对象:在JavaScript中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象(属性+方法)

类:泛指某一大类(class)
对象:通过实例化的一个具体对象

constructor构造函数

constructor()方法是类的构造函数(默认方法),用于传递参数,返回实例对象,通过new命令生成对象实例时,自动调用该方法

<script>
class Father{
   constructor(x,y){
     this.x=x;
     this.y=y;
  }
  info(){
      console.log(this.x+this.y);
   }
}

var y=new Father(2,4);
y.info();       //6

</script>

继承(extends)

子类可以继承父类的一些属性和方法

super关键字
super关键字用于访问和调用对象父类上的函数。可以调用父类的构造方法,也可以调用父类的普通函数

注意:子类在构造函数中使用super,必须放到this前面(必须先调用父类的构造方法,再使用子类的构造方法)

1.在ES6中,先定义类,才能通过类实例化对象
2.类里面的共有的属性和方法一定要加this使用

子类继承父类的构造方法

<script>
class Father{
   constructor(x,y){
     this.x=x;
     this.y=y;
  }
  info(){
      console.log(this.x+this.y).
   }
}

class Son extends Father{

}

var e = new Son(2,4);
e.info();

</script>
<script>
        class Father{
           constructor(x,y){
             this.x=x;
             this.y=y;
          }
          info(){
              console.log(this.x+this.y);
           }
        }
        
        class Son extends Father{
          constructor(x,y){

              //倘若子类已有构造函数,要想使用父类的方法,需使用super()
            super(x,y);  
          }
        }
        
        var e = new Son(2,4);
        e.info();
        
        </script>

子类继承父类的普通方法

<script>
        class Father{
           money(){
             return '年薪百万';

           }

        }

        class Son extends Father{
            money(){
                //继承父类中money()的普通方法
                console.log(super.money()+'我也可以');
            }
        }


        var t = new Son();
        t.money();

    </script>

综合

class Father{
            constructor(name){
               this.name=name;
            //    this.age=age;

            }

            info(){

                return this.name+'今年';
            }

        }

        class Son extends Father{
            constructor(name,age){
                super(name);
                // this.name=name;
                this.age=age;

            }
            info(){
                console.log(super.info()+this.age+'了');
            }b

        }
        var d = new Son('wzm',22);
        d.info();      //wzm今年22

——————————————————
在ES6之前,对象不是基于类创建的,而是用一种构造函数的特殊函数来定义对象和他们的特征

构造函数是一种特殊的函数,用来初始化对象,即为对象成员变量赋初始值,它总与new 一起使用

在js中,使用构造函数要注意:
1.构造函数用于创建某一类对象,其首字母要大写
2.构造函数要和new 一起使用才有意义

new 在执行时会做四件事
1.在内存中创建一个新的空对象
2.让this指向这个新对象
3.执行构造函数里面的代码,给这个新对象添加属性和方法
4.返回这个新对象(因此构造函数里面不需要return)

实例成员只能通过实例化对象访问
静态成员只能通过构造函数访问

function Start(name,age){
      this.name=name;
      this.age=age;
      this.skill=function(){
           console.log('敲代码')
       }
}

var g=new Start('wzm',22);
//动态
console.log(g.name);   //wzm
console.log(g.age);    //22
g.skill();
//静态
Start.sex='男';
console.log(Start.sex)    //男
console.log(g.sex)      //undefined

构造函数在创建对象时存在内存浪费的问题(主要是公共方法引起的)
创建一个对象就会占用一个内存地址,因此同一构造函数创建的对象,它们不相等

构造函数原型prototype

构造函数通过原型分配的函数是所有对象所共享的
JavaScript规定,每一个构造函数都有一个prototype属性,指向另一个对象。(这个prototype就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有)

一般情况,公共属性定义到构造函数里面,公共方法放到原型对象上

Start.prototype.skill=function(){
    //解决了内存浪费
    console.log('敲代码')}
<script>
        function Start(name,age){
              this.name=name;
              this.age=age;
            //   this.skill=function(){
            //        console.log('敲代码')
            //   }
             console.log(this.name+'今年'+this.age+'了');
        }
        Start.prototype.skill=function(){
            //解决了内存浪费
            console.log('敲代码');
        }
        
        var g=new Start('wzm',22);
        var y=new Start('lzy',18);

        //验证是否占用空间
        console.log(g.skill === y.skill)
   </script>

原型:一个对象,成为prototype为原型对象
原型的作用:共享方法

对象原型_proto_

对象都会有一个属性_proto_指向构造函数的prototype原型对象,对象能是用构造函数prototype原型对象的属性和方法,就是因为对象有_proto_原型的存在

对象._proto===构造函数._prototype_    //true

1.只要是对象就有_proto_原型,指向原型对象
2.我们Start原型对象里面的_proto_原型指向的是Object

Start._prototype_._proto_ === Object._prototype_ //true

Object._prototype_._proto_=null

Start是一个构造函数,有prototype,而prototype是一个对象,是对象就有_proto_原型,指向原型对象

原型链

对象._proto===构造函数._prototype_

构造函数._prototype_._proto_ === Object._prototype_

扩展内置对象
作用:解决构造函数原型对象中没有的方法

数组求和∑

//方法一
Array.prototype.sum=function (){
     var sum=0;   
      for(var  i=0;i<this.length;i++){  
           sum+=this[i];
             }  
           return sum;
      }
//写法二
Array.prototype={        
  sum:function {                    
        var sum=0;              
 for(var i=0;i<this.length;i++){                    
      sum+=this[i];         
 }          
  return sum;}}
var arr=[1,2,3];
console.log(arr.sum())    //6

注意:方法二行不通,原因会覆盖构造函数原型对象的方法

Call方法

作用:
1.call()可以调用函数
2.call()可以改变这个函数的this指向,此时函数就指向处理的对象

function fn(){
     console.log(11)     
     console.log(this)  //Windows对象
     }
     var y={   
      name:'wzm'};
      
      fn.call();   //11
      fn.call(y)   //将fn中的this指向y对象
<script>
   function Father (uname,age){
       this.uname=uname;
       this.age=age;
   }
   function Son(uname,age){
      Father.call(this,uname,age);
      //将Father中的this指向Son
   }
   var son=new Son('wzm',22);
   console.log(son);
</script>

拓展
改变this指向的其他两种( apply () , bind () )
apply ()

var t ={
name:'wzm'
}

function fn(arr){
  console.log(arr);
}

fn.apply(t,['lzy']);
//注意:传递的参数必须是数组(伪数组)

案例<求数组中最大的值>

var f=[];
var max=Math.max.apply(Math,f);
console.log(max);

bind()

fun.bind(被指向函数,参数)

注意:参数不一定是数组;
返回由指定的this值和初始化参数改造的原函数拷贝

   var o={
      name:'wzm';
   }
   function fn(a,b){
       console.log(a+b);
   }
   var f =fn.bind(o)  //{name:'wzm'}
   var f=fn.bind(o,1,2)    //{name:'wzm'},3
   f();
   

Es6之前,使用构造函数和原型实现面向对象编程
Es6之后,使用类实现面向对象编程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值