JavaScript中对象的创建、继承

一、对象的创建

1. 对象(字面量)

  • JS对象是一系列键值对的集合,值可以是基础类型也可以是函数或嵌套的对象,键和值用:连接,键值对之间用逗号,分隔。

    let obj={
      a:"alice",      //值为字符串
      b:function(){   //值为函数 ,使用ES6字面量增强后这行可以这么写 `b(){`
        console.log(this.a)
      },
      c:{             //值为对象
        d:1
      }
    }
    

2. 构造函数

  • 用于创建对象的函数。

  • 首字母大写来表示其是一个构造函数。

  • 使用new关键字来通过构造函数创建对象。

  • 函数定义里使用的是等号=;,而对象定义里使用的是:,

  • 相比字面量的优势是可以复用以及传递参数

    function Func(){   //表达式形式  `const Func=function(){`  ,不能使用箭头函数,因为箭头函数没有自己的this绑定
      this.a = 'alice';
      this.b = function(){
        console.log(this.a);
      };
      this.c = {d:1}
    }
    let obj = new Func()
    

3. 工厂函数

  • 工厂函数将需要构造的对象通过return返回,就不需要new关键字了,也不需要this,是一种结合构造函数和字面量的写法,
    function Func(a){   
     return {
      a,  //ES6的字面量增强写法,相当于`a:a`
      b(){   //ES6的字面量增强写法,相当于`b:function(){`
        console.log(this.a);
      },
      c :{d:1}}
    }
    let obj=Func('alice')
    

4. class(ES6)

  • 类是用于创建对象(实例)的模板(通过new关键字创建)。
  • JS 中的类建立在原型之上。
  • 类实际上是“特殊的函数”。
  • 类的主体会执行在严格模式下。
  • extend派生,super继承
  • 类的三个关键特征:
    • 构造函数constructor()
    • 实例方法和实例字段
    • 静态方法和静态字段
  • 类元素的三个特征:
    • 种类:gettersetter、方法、字段
    • 位置:静态的或位于实例上
    • 可见性:公有或私有
  • 静态:拥有static 前缀,是一组在类本身上定义的特性,而不是在类的实例上定义的特性,不能从实例中访问。
  • 私有:私有字段是以 #(井号)开头的标识符。在类外访问私有字段会导致语法错误,在浏览器控制台中运行的代码可以在类外访问私有字段,JavaScript 为了方便调试而仅在 DevTools 中放宽了这一限制。
    class Func{
        constructor(a,c){
            this.a=a;
            this.c=c;
            this.b=function(){
            console.log(this.a);
            }
        }
        e(){
            console.log(this.a);
        }
        static f(){
            console.log(this.a);
        }
        #g(){
            console.log(this.a);
        }
    }
    const obj=new Func('alice',{d:1})
    
  • b()e()f()g()的区别
    • b()可以通过实例进行访问,且会存在于创建的实例对象中。
    • e()可以通过实例进行访问,但不会存在于创建的实例对象中,而是存在于其原型(prototype)属性中。
    • f()无法通过实例进行访问,但可以通过Func.f()进行访问,需要注意的是此时Func.f()不会打印'alice',而是会打印undefined,原因是因为this此时指向Func,而Func 自身并没有a 的属性,如果想正常输出,那么需要定义一个静态statica属性,如果没有带static关键字,那么这个这个属性将作为实例属性出现在创建的实例对象中。
    • g()无法通过实例进行访问,无法在类外访问。

5. Object.create()(原型式继承)

  • Object.create(proto)以一个现有对象为原型,创建一个新对象。

6. Object.assign()

  • Object.assign(target, ...sources)将一个或者多个源对象中所有可枚举自有属性复制到目标对象(即只执行浅拷贝,嵌套对象不会被深拷贝。),并返回修改后的目标对象。
  • target也会被修改,其值就是返回值。

二、对象的继承

1. 原型链继承

  • 利用原型对象来实现继承,在JS中,每个对象都有一个原型对象。当访问一个对象的属性或方法时,如果该对象本身不存在这个属性或方法,就会在他的原型对象中查找,这样就形成了原型链。
  • __proto__prototype
    • 每个对象都有一个隐藏的内部属性[[Prototype]],而__proto__是访问或设置这个内部属性的公共接口。
    • prototype是函数(包含构造函数)的一个属性,指向一个对象,该对象会成为由该函数创建的所有实例的原型。
  • 优点和缺点:
    • 优点:简单,父类方法可以被多个子类共享,减少了代码冗余。
    • 缺点:所有子类对象共享父类的属性,相互影响。

2. 原型式继承 Object.create()

  • 以一个现有对象为原型,创建一个新对象。

3. 构造函数继承 (经典继承)

  • 在子类的构造函数中通过call()apply()方法调用父类的构造函数,将父类的属性复制到子类的对象中。

    // 定义父类构造函数
    function Parent(name) {
      this.name = name;
      this.sayHello = function() {
        console.log('Hello from ' + this.name);
      };
    }
    // 定义子类构造函数
    function Child(name) {
      Parent.call(this, name);
    }
    let child = new Child('child');
    child.sayHello(); 
    
  • 优点和缺点

    • 优点:可向构造函数传参,且每个子类对象属性相互独立。
    • 缺点:构造函数中的方法在每个对象都要重新创建,无法复用,浪费空间,且无法继承父类的原型方法。

4. 组合继承(原型链继承和构造函数继承的结合)

  • 属性通过构造函数继承
  • 方法通过原型链继承
  • 优点及缺点
    • 优点:结合了原型链继承和构造函数继承的优点
    • 缺点:在实现过程调用了两次构造函数,影响性能

5.寄生式继承

  • 在原型式继承的基础上,在函数内部增强对象,返回这个增强的对象。
  • 优点和缺点:
    • 优点:可以在继承的基础上灵活添加新的属性和方法,对已有对象进行增强。
    • 缺点:对象间共享原型属性。复用性不高。

6. 寄生组合继承

  • 解决了组合继承中父类构造函数被调用两次的问题。通过Object.create()方法来继承父类的原型,避免了子类原型上再次调用父类构造函数。

    function Parent(name) {
      this.name = name;
    }
    Parent.prototype.sayHello = function() {
      console.log('Hello from ' + this.name);
    };
    function Child(name) {
      Parent.call(this, name);
    }
    let F = Object.create(Parent.prototype);
    F.constructor = Child;
    Child.prototype = F;
    let child = new Child('child');
    child.sayHello(); 
    
  • 优点和缺点:

    • 优点:综合了组合继承的优点,且性能更好。是一种比较理想的继承方式。
    • 缺点:实现过程相对复杂,理解起来有些难度。

7. class继承(ES6)

  • 使用extends实现类的继承。

    class Parent {
        greet() { console.log("Hello!"); }
    }
    class Child extends Parent {
        sayHi() { console.log("Hi!"); }
    }
    const child = new Child();
    child.greet(); // "Hello!"
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值