轻松理解 JS 中的面向对象,顺便搞懂 prototype 和 __proto__

本文详细介绍了JavaScript中面向对象的概念,包括如何使用函数替代类,函数作为构造函数,实例方法的prototype,__proto__的作用,constructor的含义,以及静态方法和继承的实现。通过实例解释了new操作符和instanceof运算符的工作原理,帮助读者深入理解JS的面向对象编程。
摘要由CSDN通过智能技术生成

这篇文章主要讲一下JS中面向对象以及 __ proto __,ptototype和construcator,这几个概念都是相关的,所以一起讲了。

在讲这个之前我们先来说说类,了解面向对象的朋友应该都知道,如果我要定义一个通用的类型我可以使用类(class)。比如在java中我们可以这样定义一个类:

public class Puppy{
   
    int puppyAge;

    public Puppy(age){
   
      puppyAge = age;
    }

    public void say() {
   
      System.out.println("汪汪汪"); 
    }
}

上述代码我们定义了一个Puppy类,这个类有一个属性是puppyAge,也就是小狗的年龄,然后有一个构造函数Puppy(),这个构造函数接收一个参数,可以设置小狗的年龄,另外还有一个说话的函数say。这是一个通用的类,当我们需要一个两岁的小狗实例是直接这样写,这个实例同时具有父类的方法:

Puppy myPuppy = new Puppy( 2 );
myPuppy.say();     // 汪汪汪

但是早期的JS没有class关键字啊(以下说JS没有class关键字都是指ES6之前的JS,主要帮助大家理解概念,本文不涉及ES6的class),JS为了支持面向对象,使用了一种比较曲折的方式,这也是导致大家迷惑的地方,其实我们将这种方式跟一般的面向对象类比起来就很清晰了。下面我们来看看JS为了支持面向对象需要解决哪些问题,都用了什么曲折的方式来解决。

没有class,用函数代替

首先JS连class关键字都没有,怎么办呢?用函数代替,JS中最不缺的就是函数,函数不仅能够执行普通功能,还能当class使用。比如我们要用JS建一个小狗的类怎么写呢?直接写一个函数就行:

function Puppy() {
   }

这个函数可以直接用new关键字生成实例:

const myPuppy = new Puppy();

这样我们也有了一个小狗实例,但是我们没有构造函数,不能设置小狗年龄啊。

函数本身就是构造函数

当做类用的函数本身也是一个函数,而且他就是默认的构造函数。我们想让Puppy函数能够设置实例的年龄,只要让他接收参数就行了。

function Puppy(age) {
   
  this.puppyAge = age;
}

// 实例化时可以传年龄参数了
const myPuppy = new Puppy(2);

注意上面代码的this,被作为类使用的函数里面this总是指向实例化对象,也就是myPuppy。这么设计的目的就是让使用者可以通过构造函数给实例对象设置属性,这时候console出来看

myPuppy.puppyAge就是2。console.log(myPuppy.puppyAge);   // 输出是 2

实例方法用prototype

上面我们实现了类和构造函数,但是类方法呢?Java版小狗还可以“汪汪汪”叫呢,JS版怎么办呢?JS给出的解决方案是给方法添加一个prototype属性,挂载在这上面的方法,在实例化的时候会给到实例对象。我们想要myPuppy能说话,就需要往Puppy.prototype添加说话的方法。

Puppy.prototype.say = function() {
   
  console.log<
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
JavaScript ,每个对象都有一个 __proto__ 属性,指向其构造函数的原型对象。而每个函数都有一个 prototype 属性,指向该函数实例化出来的对象的原型对象。 __proto__ 属性是一个指针,指向该对象的构造函数的原型对象。通过 __proto__ 属性可以访问原型对象的属性和方法。这个属性在 ES6 已经被标准化,可以用 Object.getPrototypeOf() 来获取对象的原型。 prototype 属性是函数的一个特殊属性,指向一个对象。当函数用作构造函数创建实例对象时,该对象的原型会指向构造函数的 prototype 属性指向的对象。也就是说,该对象可以访问构造函数原型对象的属性和方法。 举个例子: ``` function Person(name) { this.name = name; } Person.prototype.sayHello = function() { console.log(`Hello, my name is ${this.name}`); } const p = new Person('Tom'); console.log(p.__proto__ === Person.prototype); // true console.log(Person.prototype.constructor === Person); // true console.log(p.constructor === Person); // true ``` 在这个例子,我们定义了一个构造函数 `Person`,并给其原型对象添加了一个 `sayHello` 方法。我们通过 `new` 关键字实例化了一个 `Person` 对象 `p`。这个对象的 `__proto__` 属性指向了 `Person.prototype`,因此我们可以通过 `p.__proto__.sayHello()` 或者 `Person.prototype.sayHello.call(p)` 来调用 `sayHello` 方法。同时,我们也可以通过 `Person.prototype` 来访问 `Person` 构造函数原型对象的属性和方法。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值