对象(类)的封装方式(面向对象的js基本知识)

上一个月一直忙于项目,没写过笔记,今天稍微空下来了一点

前几天在写项目的时候关于怎么去封装每一个组件的时候思考到几种方式,这里总结一下:

1、构造函数方式(类似java写类的方式):把所有的属性和方法全部挂在构造函数内部的this上:

 1 function Textarea(opts) {
 2     this.defaults = {
 3         //...这是一些默认属性
 4     };
 5     this.options = $.extend(true, {}, this.defaults, opts);
 6     this.creatDom = function() {
 7         //...这里面很大一堆代码
 8     };
 9     this.setVal = function() {
10         //...这是很大一堆代码
11     };
12     this.getVal = function() {
13         //...这是很大一堆代码
14     };
15 }

这种方法的优点是代码比较紧凑,比较好理解和代码的管理,但是这样我们每次实例化一个对象的时候都会新开一段内存来存储这个对象(包括方法和属性)
我们改改:

 1 function Textarea(opts) {
 2     this.defaults = {
 3         //...这是一些默认属性
 4     };
 5     this.options = $.extend(true, {}, this.defaults, opts);//这是覆盖以后的属性
 6     this.creatDom = creatDom;
 7     this.setVal = setVal;
 8     this.getVal = getVal;
 9 }
10 function creatDom() {
11     //...这是很大一堆代码
12 }
13 function setVal() {
14     //...这是很大一堆代码
15 }
16 function getVal() {
17     //...这是很大一堆代码
18 }

这样会节约一些内存:但是牺牲了代码的紧凑度;
我们可以知道,每次实例化对象的时候其实三个方法其实是公用的,所以出现了第二种方式去定义对象

2、原型式写法:把属性和方法都挂在到对象的原型上:

 1 function Textarea() {}
 2 Textarea.prototype.defaults = {
 3     //...
 4 };
 5 Textarea.prototype.options = $.extend(true, {}, this.defaults);
 6 Textarea.prototype.creatDom = function() {
 7     //...
 8 };
 9 Textarea.prototype.setVal = function() {
10     //...
11 };
12 Textarea.prototype.getVal = function() {
13     //...
14 };
15 //当然也可以把所有属性和方法放在对象上面然后再挂在prototype上:
16 function Textarea() {}
17 Textarea.prototype = {
18     defaults : {},
19     options : $.extend(true, {}, this.defaults),
20     creatDom : function() {},
21     setVal : function() {},
22     getVal : function() {}
23 };

但是这种方法是不可取的,因为这样不能通过参数来构造对象实例(一般每个对象的属性是不相同的);就像fe里面每个人名字不一致,但都能吃能笑能写代码;
举个简单的例子:

1 function Person(){}
2 Person.prototype.name = "winter";
3 Person.prototype.getName = function() { return this.name;}
4 new Person("summer").getName();//得到的还是winter的大名;

3、构造函数+原型结合的方式:

1 function Textarea(opts) {
2     this.defaults = {};
3     this.option =  $.extend(true, {}, this.defaults, opts);
4 }
5 Textarea.prototype = {
6     creatDom : function() {},
7     setVal : function() {},
8     getVal : function() {}
9 };

看看这种方式是不是很完美...
貌似还不完美,这样Textarea.prototype还是在外面,
我们把它也拿到对象里面去:如下

1 function Textarea(opts) {
2     this.defaults = {};
3     this.option =  $.extend(true, {}, this.defaults, opts);
4     Textarea.prototype = {
5         creatDom : function() {},
6         setVal : function() {},
7         getVal : function() {}
8     };
9 }

现在看似好了,但是我们每次实例化的时候会发生什么?
都会去执行这对代码:

1 Textarea.prototype = {
2     creatDom : function() {},
3     setVal : function() {},
4     getVal : function() {}
5 };

所以我们再做一个步骤,就是让它只执行一次:

 1 function Textarea(opts) {
 2     this.defaults = {};
 3     this.option =  $.extend(true, {}, this.defaults, opts);
 4     if(!!this.init){
 5         Textarea.prototype = {
 6             creatDom : function() {},
 7             setVal : function() {},
 8             getVal : function() {}
 9         };
10         this.init = true;
11     }
12 }

OK!一般说来公共属性写在prototype下,需要在实例化的时候改变的属性写在this下
另外我们在实例化对象的时候(new)的时候需要在new的过程中就执行初始化函数:
比如上面的例子我们在var textarea = new Textarea(opts);的时候就想把creatDom函数执行了而不是new Textarea(opts).creatDom();
这时候我们就需要这样:

 1 function Textarea(opts) {
 2     this.defaults = {};
 3     this.option =  $.extend(true, {}, this.defaults, opts);
 4     this.creatDom(this.options);
 5 }
 6 Textarea.prototype = {
 7     creatDom : function() {},
 8     setVal : function() {},
 9     getVal : function() {}
10 };

号外:构造函数下面的this

 1 var die = BlackBerry;
 2 function Phone(){
 3     console.log(this.die);
 4 }
 5 Phone()//BlackBerry
 6 var die = BlackBerry;
 7 function Phone(){
 8     this.die = "Nokia";
 9     console.log(this.die);
10 }
11 Phone()//Nokia

构造函数直接调用会把this当作全局window
所以以原型方式写出的对象中没有挂在this下面,直接调用构造函数将不会有这些属性和方法
如果以构造函数的方式生成对象在构造函数直接调用的时候将在window下生成相应的对象和方法

原型下面的this

 1 function Phone() {}
 2 Phone.prototype = {
 3     name : "Nokia",
 4     init : function() {
 5         this.name = "BlackBerry";
 6     }
 7 };
 8 var myPhone = new Phone();
 9 myPhone.init();
10 console.log(myPhone.name);//BlackBerry
11 console.log(Phone.prototype.name);//Nokia

init里面的this指的是什么?Phone.prototype?

这里的this指的是调用的实例化对象myPhone;而不是原型对象,看看下面:
console.log(myPhone.hasOwnProperty("name"));//true
这里为true的原因是在调用myPhone.init()是给实例化对象添加乐一个name属性

console.log(myPhone.hasOwnProperty("init"));//false
这里为false很明显,因为start是原型上面的属性而非实例化对象的属性

我差点被骗了:我以为在代码执行的时候myPhone.init();this.name = "BlackBerry";会覆盖Phone.prototype下面的那么属性

时间: 2024-10-12 15:30:32

对象(类)的封装方式(面向对象的js基本知识)的相关文章

js if for 详解 获取元素方式 及一些js 基础知识

##获取元素的新方法## --document.querySelector('Css Selector{css选择器}') 接收一个css选择器(通配,群组,类,包含,id....等) 若这个选择器对应的是一组元素,就找第0个,注意js从0开始计数.CSS计数从一开始. ##判断## 当同一种操作有两种不同结果时要用if if(判断条件){ 条件成立执行内容 }else{ 条件不成立执行内容} if括号中真正接收的是布尔值即true 或 false if(最终接收内容为true或false){

JS 基础知识2 传值和传址

要知道传址跟传址,首先我们先了解下数据值的操作. 1复制:可以把它赋值给一个新的变量 2传递:可以将他传递给一个函数或者方法 3比较:可以与另外一个值比较,判断是否相等 简要介绍下传值: 当一个数据是通过值被操作的,那么关系到的是数据的值,在赋值的过程中,是对实际值进行了COPY,储存在一个变量或者属性或数组中,copy的值与原数据是相互独立的. 当数据通过值传递给一个函数时,数据的一份传递给这个函数,如果函数体修改了这个值,只在函数体受影响,函数外的原数据不受影响. 当一个数据通过值和另外一个

JS类的封装及实现代码

js并不是一种面向对向的语言, 没有提供对类的支持, 因此我们不能像在传统的语言里那样 用class来定义类, 但我们可以利用js的闭包封装机制来实现js类, 我们来封装一个简的Shape类. 1. 定义js类 js并不是一种面向对向的语言, 没有提供对类的支持, 因此我们不能像在传统的语言里那样 用class来定义类, 但我们可以利用js的闭包封装机制来实现js类, 我们来封装一个简的Shape类. 代码如下: function ShapeBase() { this.show = functi

JS类的封装及实现代码(转)

js并不是一种面向对向的语言, 没有提供对类的支持, 因此我们不能像在传统的语言里那样 用class来定义类, 但我们可以利用js的闭包封装机制来实现js类, 我们来封装一个简的Shape类. 1. 定义js类 js并不是一种面向对向的语言, 没有提供对类的支持, 因此我们不能像在传统的语言里那样 用class来定义类, 但我们可以利用js的闭包封装机制来实现js类, 我们来封装一个简的Shape类. 代码如下: function ShapeBase() { this.show = functi

Python 基础之面向对象初识与类的封装

一: 面向对象类的初识#(1) 类的定义#三种方式:#1.class MyClass:    pass #2.推荐class MyClass():    pass #3.class MyClass(object):    pass#(2) 类的实例化class MyClass():    pass#类的实例化,实例化对象obj = MyClass() #obj 就是一个对象#(3)类的基本结构只有成员方法和成员属性对象.属性  对象.方法()#例:class MyClass():    #成员属

JavaScript学习12 JS中定义对象的几种方式【转】

avaScript学习12 JS中定义对象的几种方式 转自:  http://www.cnblogs.com/mengdd/p/3697255.html JavaScript中没有类的概念,只有对象. 在JavaScript中定义对象可以采用以下几种方式: 1.基于已有对象扩充其属性和方法 2.工厂方式 3.构造函数方式 4.原型("prototype")方式 5.动态原型方式 一.基于已有对象扩充其属性和方法 <script type="text/javascript

JavaScript学习12 JS中定义对象的几种方式

JavaScript学习12 JS中定义对象的几种方式 JavaScript中没有类的概念,只有对象. 在JavaScript中定义对象可以采用以下几种方式: 1.基于已有对象扩充其属性和方法 2.工厂方式 3.构造函数方式 4.原型("prototype")方式 5.动态原型方式 一.基于已有对象扩充其属性和方法 <script type="text/javascript"> var object = new Object(); object.name

JS类的封装

js并不是一种面向对向的语言, 没有提供对类的支持, 因此我们不能像在传统的语言里那样 用class来定义类, 但我们可以利用js的闭包封装机制来实现js类 1. 定义js类 js并不是一种面向对向的语言, 没有提供对类的支持, 因此我们不能像在传统的语言里那样 用class来定义类, 但我们可以利用js的闭包封装机制来实现js类, 我们来封装一个简的Shape类. function ShapeBase() { this.show = function() { alert("ShapeBase

JavaScript 面向对象的编程(二) 类的封装

类的定义 方式一 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 =