这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战
面向对象(上)
在Java中我们有类和实例的概念,来帮助我们理解面向对象的编程。
但是在JS中不区分类和实例的概念,而是通过原型prototype来实现的。
我们从最开始的基础类型中的对象来了解
var Person = {
name: '',
age: 0
}
这是一个Person"对象",他有name和age两个属性。
我们来创建一个路人A。
var personA = {};
personA.name = '路人';
personA.age = 20;
这样我们就创建了一个对象,并且把两个属性给加入到这个对象当中。
但是他的缺点也非常明显,第一是麻烦,第二是personA和Person之间,除了变量名外没有任何联系。
我们先来解决麻烦的问题。
我们把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中他还让personA和Person有了联系。
当使用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.cry和Person.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是怎么知道该调用哪个的呢?