面向对象编程就是将你的需求抽象成一个对象,然后针对这个对象分析其特性(属性)与动作(方法)。这个对象我们称之为类。面向对象编程思想其中有一个特点就是封装,就是说把你需要的功能放到一个对象里。
# 1. javascript 当中的 prototype
在 js 当中,constructor 属性是专门为 function 而设计的,她存在于每一个 function的prototype 属性中。constructor 保存了指向 function 的一个引用。同时,实例化(new 操作符)的 book 的proto 属性是函数 prototype 的一个内部引用
var Book = function(id,bookname,price) {
this.id = id;
this.bookname = bookname;
this.price = price;
}
Book.prototype.display = function(){
console.log(this.bookname);
}
var book = new Book(10,'javascript ',55);
console.log(book.__proto__.constructor === Book) //true
console.log(Book.prototype.constructor === Book) //true
console.log(Book.prototype.isPrototypeOf(book)) //true
在上面的代码当中,如果写成
Book.prototype = {
display: function(){
cosole.log('display');
}
}
console.log(Book.prototype.constructor === Book) //false
因为 constructor 被覆盖掉了,针对这种情况,可以按照这种方式去写:
Book.prototype = {
constructor:Book,
display: function(){
cosole.log('display');
}
}
console.log(Book.prototype.constructor === Book) //true
# 2. 验证 prototype 属性
isPrototypeOf()
这个方法用来判断某个 prototype 对象与某个实例的关系
console.log(Book.prototype.isPrototypeOf(book)) //true
hasOwnProperty()
每个实例对象都有一个 hasOwnProperty()方法,用来判断某一个属性到底是本地属性,还是继承自 prototype 的属性。
book.hasOwnProperty('id'); //true
book.hasOwnProperty('display'); //false
in 运算符 可以用来判断某个实例是否含有某个属性,不管是不是本地属性。
console.log('id' in book); //true
console.log('display' in book) //true
in 运算符还可以用来遍历某个对象的所有属性
for(var prop in book){
console.log("book["+ prop +"]="+book[prop]);
}
/**
book[id]=10
book[bookname]=javascript
book[price]=55
book[display]=function (){
console.log(this.bookname);
}
**/
# 3. 闭包实现一个完整的类
有时候我们经常将类的静态变量通过闭包来实现
var Book = (function(){
//静态私有变量
var bookNum = 0;
//静态私有方法
function checkBook(name){
console.log(name);
}
//创建类
function _book(newId,newName,newPrice){
// 私有变量
var name,price;
function checkID(id){}
//特权方法
this.getName = function(){}
this.getPrice = function(){}
this.setName = function(){}
this.setPrice = function(){}
//公有属性
this.id = newId;
//公有方法
this.copy = function(){}
bookNum ++;
if(bookNum > 100){
throw new Error('我们仅出版100本书');
}
this.setName(name);
this.setPrice(price);
}
_book.prototype = {
isJSbook :false,
display: function(){}
}
return _book;
})();
闭包有权访问另外一个函数作用域中的变量的函数,即在一个函数内部创建另外一个函数。我们将这个闭包作为创建对象的构造函数,这样它既是闭包又是可实例对象的函数,即可以访问到类函数作用域中的变量(booknum,checkBook)。
同时在闭包内部实现了原型属性和方法,最终得以返回一个完整的类。