面向对象
面向对象与面向过程
面向对象就是将你的需求抽象成一个对象, 然后针对这个对象分析其特性(属性)与动作(方法). 这个对象我们称之为类. 面向对象编程思想其中一个特点就是封装,就是说把你需要的功能放在一个对象里.
封装
-
创建一个类(两种方法)
(1):声明一个函数保存在一个变量里, 变量首字母大写.这个函数(类)内部通过对this变量添加属性或者方法:
使用 = 方式调用var Book = function(id, bookname, price){ this.id = id this.bookname = bookname this.price = price }
(2): 通过类原型
Book.prototype.display = function(){} // of Book.prototype = { display: function(){} }
使用new 关键字调用
var book = new Book ()
通过this和prototype的区别:
通过this添加的属性,方法是在当前对象上添加的, 然而JS是一种基于原型prototype的语言, 所以每创建一个对象(JS中函数也是对象)时,它都有一个原型prototype用于指向其继承的属性,方法.这样通过prototype继承的方法并不是对象本身的, 所以使用这些方法时,需要通过prototype一级一级查找来得到.通过this定义的属性或者方法时该对象自身拥有的,所以我们每次通过类创建一个新对象时, this指向的属性和方法都会得到响应的创建,而通过prototype继承的属性或者方法是每个对象通过prototype访问到的,所以我们每次通过类创建一个新对象时这些属性和方法不会再次创建 -
属性与方法封装
(1)私有变量,私有方法
由于JS的函数级作用域,声明在函数内部的变量以及方法在外界时访问不到的,通过此特性即可创建类的私有变量以及方法. 然而在函数内部通过this创建的属性和方法,在类创建对象时,每个对象自身都拥有一份并且可以在外部访问到,因此通过this创建的属性可看作是对象的公有属性与方法,而且还能访问到类(创建时)或者对象自身的私有属性和私有方法, 由于这些方法的特权比较大, 所以我们又将它看作为特权方法.在创建对象时通过这些特权方法我们可以初始化一些属性, 因此这些在创建对象时调用的特权方法还可以看作是类的构造器.// 私有属性与私有方法, 特权方法,对象公有属性和对象公有方法,构造器 var Book = function(id, name, price){ // 私有属性 var num = 1; // 私有方法 function checkId(){}; // 特权方法 this.getName = function(){}; this.getPrice = function(){}; this.setName = function(){}; this.setPrice = function(){}; // 对象公有属性 this.id = id; // 对象公有方法 this.copy = function(){}; // 构造器 this.setName(name); this.setPrice(price) } // 静态公有属性(对象不能访问) Book.isChinese = truel // 类静态公有方法(对象不能访问) Book.resetTime = function(){ console.log(123) } Book.prototype = { // 公有属性 jsBook: false, // 公有方法 display : function(){} } var b = new Book(11, 'JS', 50); console.log(b.num); // undefined console.log(b.jsBook); // false console.log(b.id); // 11 console.log(b.isChinese); // undefined console.log(Book.isChinese) // true Book.resetTime(); // 123
-
闭包实现
// 利用闭包实现 var book = (function(){ // 静态私有变量 var bookNum = 0; // 静态私有方法 function checkBook(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() {}; if(bookNum > 100) throw new Error('我们仅出版一百本书') // 构造器 this.setName(name); this.setPrice(price); } __book.protopy = { // 静态公有属性 isJSBook : false, // 静态公有方法 display : function(){} } })()
-
创建对象的安全模式
// 图书类 var Book = function(title, time, type){ this.title = title; this.time = time; this.type = type; } var book = Book('Js', '2031', 'js') console.log(book) // undefined console.log(window.title) // Js console.log(window.time) // 2031 console.log(window.type) // js
上面的示例由于没有使用new 关键字来实例化, 所以函数在全局作用域执行了,所以在全局作用域中this指向当前对象就是全局对象window, 由于函数中没有return语句, 这个Book变量最终不会告诉book执行结果,所以就是undefined
安全模式// 图书安全类 var Book = function(title, time, type){ // 判断执行过程中this是否是当前这个对象(如果是说明是new创建的) if(this instanceof Book){ this.title = title; this.time = time; this.type = type; }else{ return new Book(title, time, type) } } var book = Book('Js', '2031', 'js') console.log(book) // Book console.log(window.title) // undefined console.log(window.time) // undefined console.log(window.type) // undefined console.log(book.title) // Js console.log(book.time) // 2031 console.log(book.type) // js