深入浅出谈js面向对象

xiaoxiao2021-02-28  93

在js里面创建一个类很容易,声明一个函数保存在一个变量(类名   首字母大写),然后在这个函数内部的this指针指向的是该类创建的实例对象,通过对this变量添加属性和方 法以实现对类添加属性和方法! var Book = function(id,bookName,price){ this.id = id; this.bookName = bookName; this.price = price; this.display = function(){ console.log(this.bookName+"的价格是"+this.price); } }类创建好了,我们可以通过类实例化对象了

var book = new Book("001","javascript",20); console.log(book.id); console.log(book.bookName); console.log(book.price); book.display();

如果你有过Java C++面向对象的基础,你会发现,Book的属性即方法都是public类型的,那么如何创建私有属性和方法呢?并且如果我还想使得在类外部只能通过特权方法来访问私有属性,那该怎么做呢?

var Book = function(id,bookName,price){ //bookName是私有属性 //特权方法 只能通过set get方法对私有属性进行访问 this.getName = function(){ return bookName; } this.setName = function(name){ bookName = name; } //对象公有属性 this.id = id; this.price = price; } 可以看出,想创建对象的私有方法,在函数里面的局部变量就具有天然私有性质,你只需要创建对应的特权方法,并把它挂载到this上面,即实例对象上面,就相当于创建了闭包函数,而被闭包引用的bookName变量就不会在构造函数执行完销毁。

var book = new Book("001","javascript",20); console.log(book.bookName); //undefined console.log(book.getName()); //"javascript"所以此时,你就不能直接通过点运算符访问book对象的bookName属性,只能通过取值器访问。

那么,问题又来了,所有的方法都应该挂载到this上吗?由于在通过构造函数实例化对象时,this指针始终指向实例对象,所以挂载到this上的方法每个对象都有一份副本,这会造成内存的大大浪费,比如第一个例子中的Book对象的display方法,其实完全可以写在Book的原型对象上面。这样使得,所有对象都共享Book原型上的属性和方法,减少内存开销。

var Book = function(id,bookName,price){ this.id = id; this.bookName = bookName; this.price = price; } Book.prototype.display = function(){ console.log(this.bookName+"的价格是"+this.price); }那么,Book创建的所有对象真的是共享display方法吗??试试就知道

var book1 = new Book("001","javascript",20); var book2 = new Book("002","javaWeb",20); console.log(book1.display===book2.display); //true答案显然,是共享,那么你可能又会问,那么display函数里面的this指针指向谁?是book1对象还是book2对象,那么在这里告诉你,this指针始终指向调用它的对象,所以谁调用指向谁。那么,为什么所有的对象共享原型对象上的方法呢,是因为其实每个实例有一个__proto__指针指向Book的原型对象。 那么在Java面向对象中还有类的静态公有属性和方法,那么在js里面怎么实现?

Book.isChinese = true; //类的静态公有属性(对象不能访问) 那么类的静态私有属性和方法怎么实现呢??既然是做变量被保护,显然,答案是 闭包

var Book = (function(){ var bookNum = 0; //静态私有变量 function checkBook(){ //静态私有方法 } //将构造函数作为闭包函数返回 return function(id,bookName,price){ bookNum++; ..... if(bookNum>100){ throw new Error("我们仅仅出版100本书"); } } })();上面代码中,bookNum是静态私有属性,只能在Book类内部访问。类的实例对象也不能访问~~在外部,通过Book.bookNum也不能访问。

那么上面我们已经知道如何创建公有属性 私有属性  静态属性了,接下来,我还想聊聊创建对象的安全模式

因为你可能写了一个Book构造函数 ,你希望别人通过new来创建实例,可以别人可能当普通函数调通了,这时候你会发现全局变量下莫名其妙多了一些id等属性,因为当成普通函数调用构造函数时,this指向window对象,那么你可以用一种安全模式来解决

var Book = function(id,bookName,price){ //判断执行过程中this对象是否是当前这个对象(如果是说明是new创建的) if(this instanceof Book){ this.id = id; this.bookName = bookName; this.price = price; }else{ return new Book(id,bookName,price); } } var book = Book("001","javascript",20); console.log(book.id);你会发现  这个时候你再也不用担心你的别人把你的构造函数当成普通函数调用了~·~~是不是很棒棒

转载请注明原文地址: https://www.6miu.com/read-37666.html

最新回复(0)