一、封装
在我们日常的开发当前,封装是非常重要的,而且也是很有必要的。当我们创建一个类,类的内部封装了属于自己的属性和方法,当我们使用时,通过new 关键字创建出对象然后在通过点语法的形式调用。
1、创建一个类
创建一个类,类的变量名一般是首字母为大写,命名规则当然是最好能见名思其意
var Book = new Book(){
// ...
}
2、给类添加属性和方法
给类添加属性和方法有2中
(1)通过this
在函数(类)的内部通过对this(函数内部自带的一个变量,用于指向当前这个对象)变量添加属性或方法。例如:
var Book = new Book(id,bookName,price){
this.id = id;
this.bookName = bookName;
this.price = price;
}
(2)通过prototype
通过在类的原型(类也是一个对象,也有原型prototype)上 添加属性和方法。有2种方法,但是不能混着使用
①一一为原型对象属性赋值
Book.prototype.display = function(){
//...
}
②将一个对象赋值给类的原型对象
Book.prototype = {
display:function(){}
}
两者方式添加属性和方法的区别:
1、我们每次通过类创建一个新对象时,this指向的属性和方法都会得到相应的创建。(就是每实例化要给对象,this指向的属性和方法都会重新创建一次,赋给到实例化的对象)。
2、通过prototype继承的属性或方法是每个实例化对象通过prototype访问到的,所以我们每次通过类创建一个新对象时,这些属性和方法不会再次创建。这种方法更好,减少性能的开销。
3、类的使用
这时候属性和方法都封装到Book类里面,我们直接通过new 关键字来实例化(创建)新的对象,然后再使用实例化的对象(新创建的对象)通过点语法的方式调用属性或方法
var book = new Book(1,'javascript设计模式',50)
console.log(book.id)
补充一个小点:
new 一个对象,类的函数内部发生了什么?
①创建了一个新对象。
②将构造函数的作用域赋值给了新对象,并把通过this创建的属性和方
法,赋值给this对象。
③返回新对象
4、类方法的分类
(1)私有属性和私有方法
在函数内部声明的变量、方法(外界是访问不到的),私有方法可以访问私有属性和私有方法。但是不能访问共有属性和共有方法
(2)共有属性和共有方法(特权方法)
通过this创建的属性和方法,他们能够访问到对象的共有属性和共有方法,还可以访问对象自身的私有属性和私有方法。
在对象创建时通过使用这些特权方法,我们可以初始化实例对象的一些属性,因此这些在创建对象时调用的特权方法还可以看作是类的构成器。
var Book = function(id){
// 私有属性
var name = 'javascript'
// 私有方法
function getId(){
console.log(name)
}
// 公有属性
this.id = id;
// 公有方法
this.getName = function(){
console.log(this.id)
}
// 构造器(初始化共有方法)
this.getName()
}
(3)静态属性和静态方法
在类的外部通过点语法定义的属性和方法。通过点语法创建的属性和方法,通过new 创建的对象是获取不到的。这是因为通过new 关键字创建新对象时,类外面通过点语法添加的属性和方法没有执行到,所以新创建的对象中无法获取他们。但是他们可以通过类来使用。
Book.isChinese = true
Book.resetTime = function(){
console.log('我是静态方法')
}
var book = new Book(1)
console.log(Book.isChinese)
(4)共有属性和共有方法
类通过prototype创建的属性或者方法在类实例的对象中是可以通过this访问到的,所以我们将prototype对象中的属性和方法称为共有属性和共有方法
Book.prototype = {
isJsBook:true,
display:function(){
console.log('我是共有方法')
}
}
var book = new Book(1)
book.display()
注意哟,给类的prototype添加属性或方法时,必须在实例化对象前,否则是获取不到的。
通过new关键字创建的对象实质是对新对象this的不断赋值,并将prototype指向类的prototype所指向的对象,而类的构造函数外面通过点语法定义的属性方法是不会添加到新创建的对象上去的。
二、闭包
闭包是有权访问另外一个函数作用域中变量的函数,即在一个函数内部创建另外一个函数。
var Book = (function(){
// 静态私有变量
var bookNum = 0;
// 静态私有方法
function chekBook(name){}
return function(newId,newName,newPrice){
// 私有变量
var name,price;
// 私有方法
function checkID(ID){
}
// 特权方法
this.getName = function(){}
this.setName = function(name){}
// 公有属性
this.id = newId
this.copy = function(){}
bookNum++
if(bookNum>100){
throw new Error('我们仅出版100本书')
}
this.setName(name)
}
})()
Book.prototype = {
isJSBook:false,
display:function(){}
}
export default Book
还可以写成另外一种形式
var Book = (function(){
// 静态私有变量
var bookNum = 0;
// 静态私有方法
function chekBook(name){}
function _book(newId,newName,newPrice){
// 私有变量
var name,price;
// 私有方法
function checkID(ID){
}
// 特权方法
this.getName = function(){}
this.setName = function(name){}
// 公有属性
this.id = newId
this.copy = function(){}
bookNum++
if(bookNum>100){
throw new Error('我们仅出版100本书')
}
this.setName(name)
}
_book.prototype = {
isJSBook:false,
display:function(){}
}
return _book
})()
export default Book
三、安全模式
创建对象的时候,由于不适应使用new这种方式,所以经常容易忘记使用new关键字、
我们来看下面的代码
Book.js
var Book = function(title,time,type){
this.title = title;
this.time = time ;
this.type = type;
}
..................................
index.js
var book = Book('javascript',2019,'js')
console.log(book) // undefined
console.log(book.title) // undefined
console.log(window.title) // javascript
打印的结果,book为undefined,这是因为我们没有使用new实例化对象,而是直接调用了Book这个函数,函数里面的this指向的是全局变量window,并且没有返回值。所以book打印出来的是undefined,而window下却能获取title
网友评论