1.JavaScript类
类与面向对象编程密不可分,面向对象编程就是将需求抽象成一个对象(类),然后针对这个对象分析其特征(属性)与动作(方法)。它的一个特点就是封装,即把需要的功能放在一个对象里。
如何在JavaScript中创建一个类?
1.ES5
首先声明一个函数保存在一个变量里,然后在这个函数(这个函数就可以称为类)的内部通过对this变量添加属性名或者方法来实现对类添加属性或者方法
var Book = function(id, bookname, price){
this.id = id;
this.bookname = bookname;
this.price = price;
}
以上创建了一个类Book(类名首字母大写),这种创建类的方式也叫构造函数模式。也可以在类的原型上添加属性和方法,有两种方式
Book.prototype.display = function(){};
Book.prototype = {
display: function(){}
};
这样我们就可以将需要的方法和属性都封装在Book类里面了,当我们调用此方法时,需要使用New关键字以实例化新的对象
var newBook = new Book(10, "JavaScript", 50);console.log(newBook.bookname); //JavaScript
通过new关键字实例化对象其实经历了一个简要的内部步骤:首先创建一个新对象newBook,然后将构造函数Book的作用域赋值给它,因此this就指向Book,最后再执行各种想要的方法。 那么我们再来分析以下代码
Book(10, "JavaScript", 50);//如何调用?window.id; //10
从上面的结果我们可以分析得到:当调用Book构造函数时,没有将其赋值给新对象,故this指向的作用域就是全局作用域,我们就可以通过window对象调用Book构造函数里面的方法了。
2.ES6
ES6中引入了Class(类)的概念,通过class关键字,极大地方便了类的创建与使用,将上述在原型中添加属性的代码用class改写如下
class Book{
constructor(id, bookname, price){
this.id = id;
this.bookname = bookname;
this.price = price;
}
display(){
//...
}}
//等价于
var Book = function(id, bookname, price){
this.id = id;
this.bookname = bookname;
this.price = price;};
Book.prototype = {
display: function(){}
};
class省略了function的书写。
最后再来看看通过点语法在函数内部添加属性与通过prototype创建属性的区别
在函数内部通过点语法添加属性,当使用new操作符创建新的Book实例时,相应的this指向这个新的实例,所以id和bookname等这些内部方法也会被创建,也就是说每定义一个函数,就实例化了一个对象,每个方法在每个实例上重新创建了一遍,通过prototype每次创建一个新对象时这些属性和方法不会被重新创建。
2.封装
函数内部作用域在外部环境是不能访问内部作用域中的私有属性和私有方法,而通过this创建的方法或属性在外部环境却能访问到,故this定义的这些方法或属性称为共(公)有属性和共(公)有方法,统称为特权方法。
var Book = function(id, name, price){
var num = 1; //私有属性
function checkId(){}; //私有方法
this.getName = function(){}; //特权方法
this.id = id; //对象公有属性
this.setName(name);
this.setPrice(price); //构造器}
在通过new关键字实例化对象时,通过this定义的方法能被访问到,但是上述代码中的私有属性却不能访问,这是因为实例化对象将作用域移到了外部实例对象,通过外部不能访问到内部的私有属性,而this定义的方法会将此方法的作用域指向实例化的对象。
那么如果方法是通过点语法或者原型模式创建,外部能否访问到这些方法呢?
Book.isChinese = true;Book.resetTime = function(){
console.log('new time')
};
Book.prototype = {
jsJSBook : false,
display: function(){}
}
当使用new关键字创建新的对象时,在类外面通过点语法添加的属性和方法并没有被执行到,所以新的对象无法被获取,在类外通过点语法定义的属性叫静态共有属性,定义的方法叫静态共有方法;通过原型prototype定义的属性和方法分别叫公有属性和公有方法,因为新对象的原型prototypr和Book类的的原型prototype指向同一个对象,即Book.prototype.isPrototypeof(newBook),所以创建的新的对象能访问到在类的外部通过原型创建的公有属性和公有方法。