JS学习快速笔记(六)

145 阅读2分钟

这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战

面向对象(上)

在Java中我们有类和实例的概念,来帮助我们理解面向对象的编程。

但是在JS中不区分类和实例的概念,而是通过原型prototype来实现的。

我们从最开始的基础类型中的对象来了解

var Person = {
  name: '',
  age: 0
}

这是一个Person"对象",他有nameage两个属性。

我们来创建一个路人A。

var personA = {}; 
personA.name = '路人';
personA.age = 20;

这样我们就创建了一个对象,并且把两个属性给加入到这个对象当中。

但是他的缺点也非常明显,第一是麻烦,第二是personAPerson之间,除了变量名外没有任何联系。

我们先来解决麻烦的问题。

我们把Person改造成函数

function Person(name,age){
  return {
    name:name,
    age:age
  }
}

这样当我们创建对象的时候就可以调用方法

var personA = Person('路人',20);

那么学过Java的同学,肯定很容易发现这很像Java中构造函数。而JS也有构造函数。

当我们使用new运算符使用构造函数,就能生成实例。而在JS中的构造函数就是一个普通函数,但是他的内部使用了this关键字。

当我们用new创建对象的时候,this就会绑定给当前实例。于是...

function Person(name,age){
  this.name = name;
  this.age = age;
}
​
var personA = new Person('路人',20);
console.log(personA.name);//路人

这与Java中创建实例非常像,这样就解决了麻烦的问题。同时在JS中他还让personAPerson有了联系。

当使用new创建对象后,它会自动含有一个constructor属性,指向构造函数。JS也提供了验证方式。

console.log(personA.constructor == Person); //true

虽然看上去构造方法很方便,但是他会造成内存浪费。我们往下看...

//我们给Person对象加一个方法
function Person(name,age){
  this.name = name;
  this.age = age;
  this.cry = function(){
    console.log(this.name + "在哭...");
  };
}
​
//在这种情况下当我们创建多个对象时
var personA = new Person('A',20);
var personB = new Person('B',22);
var personC = new Person('C',24);
//我们就能发现,他们的每个`cry`函数都一样,但都各自占了一份内存空间。

所以我们需要一种新的方式创建对象的方法。

JS提供了prototype属性,我们把自定义的方法挂载在这个属性上,我们的实例对象调用这个方法的时候,就能会统一调用prototype中挂载的这个方法。

function Person(name){
  this.name = name;
}
​
Person.prototype.cry = function(){
  console.log('Person.prototype.cry....');
};
​
var personA = new Person("A");
​
personA.cry(); // Person.prototype.cry....

接下来,可能有同学会发现,如果我们在Person同时添加this.cryPerson.prototype.cry两种方法,那么personA.cry()会调用什么方法?我们来试一下。

function Person(name){
  this.name = name;
  this.cry = function(){
    console.log("this.cry...");
  };
}
​
Person.prototype.cry = function(){
  console.log("Person.prototype.cry...");
};
​
var personA = new Person('xiaoming');
​
personA.cry(); //输出this.cry...

这时我们会发现他输出的是this.cry,那么JS是怎么知道该调用哪个的呢?