对象(类)的封装方式(面向对象的js基本知识)
上一个月一直忙于项目,没写过笔记,今天稍微空下来了一点
前几天在写项目的时候关于怎么去封装每一个组件的时候思考到几种方式,这里总结一下:
1、构造函数方式(类似java写类的方式):把所有的属性和方法全部挂在构造函数内部的this上:
function Textarea(opts) {
this.defaults = {
//...这是一些默认属性
};
this.options = $.extend(true, {}, this.defaults, opts);
this.creatDom = function() {
//...这里面很大一堆代码
};
this.setVal = function() {
//...这是很大一堆代码
};
this.getVal = function() {
//...这是很大一堆代码
};
}
这种方法的优点是代码比较紧凑,比较好理解和代码的管理,但是这样我们每次实例化一个对象的时候都会新开一段内存来存储这个对象(包括方法和属性)
我们改改:
function Textarea(opts) {
this.defaults = {
//...这是一些默认属性
};
this.options = $.extend(true, {}, this.defaults, opts);//这是覆盖以后的属性
this.creatDom = creatDom;
this.setVal = setVal;
this.getVal = getVal;
}
function creatDom() {
//...这是很大一堆代码
}
function setVal() {
//...这是很大一堆代码
}
function getVal() {
//...这是很大一堆代码
}
这样会节约一些内存:但是牺牲了代码的紧凑度;
我们可以知道,每次实例化对象的时候其实三个方法其实是公用的,所以出现了第二种方式去定义对象
2、原型式写法:把属性和方法都挂在到对象的原型上:
function Textarea() {}
Textarea.prototype.defaults = {
//...
};
Textarea.prototype.options = $.extend(true, {}, this.defaults);
Textarea.prototype.creatDom = function() {
//...
};
Textarea.prototype.setVal = function() {
//...
};
Textarea.prototype.getVal = function() {
//...
};
//当然也可以把所有属性和方法放在对象上面然后再挂在prototype上:
function Textarea() {}
Textarea.prototype = {
defaults : {},
options : $.extend(true, {}, this.defaults),
creatDom : function() {},
setVal : function() {},
getVal : function() {}
};
但是这种方法是不可取的,因为这样不能通过参数来构造对象实例(一般每个对象的属性是不相同的);就像fe里面每个人名字不一致,但都能吃能笑能写代码;
举个简单的例子:
function Person(){}
Person.prototype.name = "winter";
Person.prototype.getName = function() { return this.name;}
new Person("summer").getName();//得到的还是winter的大名;
3、构造函数+原型结合的方式:
function Textarea(opts) {
this.defaults = {};
this.option = $.extend(true, {}, this.defaults, opts);
}
Textarea.prototype = {
creatDom : function() {},
setVal : function() {},
getVal : function() {}
};
看看这种方式是不是很完美...
貌似还不完美,这样Textarea.prototype还是在外面,
我们把它也拿到对象里面去:如下
function Textarea(opts) {
this.defaults = {};
this.option = $.extend(true, {}, this.defaults, opts);
Textarea.prototype = {
creatDom : function() {},
setVal : function() {},
getVal : function() {}
};
}
现在看似好了,但是我们每次实例化的时候会发生什么?
都会去执行这对代码:
Textarea.prototype = {
creatDom : function() {},
setVal : function() {},
getVal : function() {}
};
所以我们再做一个步骤,就是让它只执行一次:
function Textarea(opts) {
this.defaults = {};
this.option = $.extend(true, {}, this.defaults, opts);
if(!!this.init){
Textarea.prototype = {
creatDom : function() {},
setVal : function() {},
getVal : function() {}
};
this.init = true;
}
}
OK!一般说来公共属性写在prototype下,需要在实例化的时候改变的属性写在this下
另外我们在实例化对象的时候(new)的时候需要在new的过程中就执行初始化函数:
比如上面的例子我们在var textarea = new Textarea(opts);的时候就想把creatDom函数执行了而不是new Textarea(opts).creatDom();
这时候我们就需要这样:
function Textarea(opts) {
this.defaults = {};
this.option = $.extend(true, {}, this.defaults, opts);
this.creatDom(this.options);
}
Textarea.prototype = {
creatDom : function() {},
setVal : function() {},
getVal : function() {}
};
号外:构造函数下面的this
var die = BlackBerry;
function Phone(){
console.log(this.die);
}
Phone()//BlackBerry
var die = BlackBerry;
function Phone(){
this.die = "Nokia";
console.log(this.die);
}
Phone()//Nokia
构造函数直接调用会把this当作全局window
所以以原型方式写出的对象中没有挂在this下面,直接调用构造函数将不会有这些属性和方法
如果以构造函数的方式生成对象在构造函数直接调用的时候将在window下生成相应的对象和方法
原型下面的this
function Phone() {}
Phone.prototype = {
name : "Nokia",
init : function() {
this.name = "BlackBerry";
}
};
var myPhone = new Phone();
myPhone.init();
console.log(myPhone.name);//BlackBerry
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下面的那么属性
对象(类)的封装方式(面向对象的js基本知识)的更多相关文章
- Learn day6 模块pickle\json\random\os\zipfile\面对对象(类的封装 操作 __init__)
1.模块 1.1 pickle模块 # ### pickle 序列化模块 import pickle """ 序列化: 把不能够直接存储的数据变得可存储 反序列化: 把数 ...
- js if for 详解 获取元素方式 及一些js 基础知识
##获取元素的新方法## --document.querySelector('Css Selector{css选择器}') 接收一个css选择器(通配,群组,类,包含,id....等) 若这个选择器对 ...
- linux下线程的两种封装方式
在网络编程的时候往往需要对Linux下原生的pthread库中的函数进行封装,使其使用起来更加方便,封装方法一般有两种:面向对象和基于对象,下面将分别介绍这两种方式,最后统一分析这两种方式的优缺点: ...
- js面向对象(对象/类/工厂模式/构造函数/公有和原型)
https://www.cnblogs.com/sandraryan/ 什么是对象 js中一切都是对象(有行为和特征).js允许自定义对象,也提供了内建对象(string date math等) 对象 ...
- JS类的封装及实现代码
js并不是一种面向对向的语言, 没有提供对类的支持, 因此我们不能像在传统的语言里那样 用class来定义类, 但我们可以利用js的闭包封装机制来实现js类, 我们来封装一个简的Shape类. 1. ...
- JavaScript学习12 JS中定义对象的几种方式【转】
avaScript学习12 JS中定义对象的几种方式 转自: http://www.cnblogs.com/mengdd/p/3697255.html JavaScript中没有类的概念,只有对象. ...
- JS类继承常用方式发展史
JS类继承常用方式发展史 涉及知识点 构造函数方式继承 1-继承单个对象 1.1 多步走初始版 1.2 多步走优化版 1.3 Object.create()方式 2-继承多个对象 2.1 遍历 Obj ...
- python中的面向对象学习以及类的封装(这篇文章初学者一定要好好看)
这篇文章对于初学者可以很有效的理解面对过程.面对对象 一.首先介绍一下面向过程和面向对象的比较: 面向过程 VS 面向对象 编程范式 编程是程序员用特定的语法+数据结构+算法组成的代码来告诉计算机如何 ...
- 09_Java面向对象_第9天(类、封装)_讲义
今日内容介绍 1.面向对象思想 2.类与对象的关系 3.局部变量和成员变量的关系 4.封装思想 5.private,this关键字 6.随机点名器 01面向对象和面向过程的思想 A: 面向过程与面向对 ...
随机推荐
- JSP中的TAG
http://blog.csdn.net/hongweigg/article/details/12006849 JSP标签有两种实现方法,一种是使用tag 文件,一种是使用tld文件. 1.使用tag ...
- Java多线程技术学习笔记(一)
目录: 概述 多线程的好处与弊端 JVM中的多线程解析 多线程的创建方式之一:继承Thread类 线程的状态 多线程创建的方式之二:实现Runnable接口 使用方式二创建多线程的好处 多线程示例 线 ...
- 给eclipse装一些插件
最近换了一个环境,需要折腾一个新的eclipse配置,所以在这里记录下. 1.安装marketplace help=>install,输入地址:http://download.eclipse.o ...
- [转载]GMT地形数据总结
[转载]GMT地形数据总结 原文地址:GMT地形数据总结作者:Jason 转载:http://seisman.info/gmt-topo-grid-datas.html 目前接触到的地形数 ...
- 安卓高手之路之 WindowManager
安卓中的画面不是纯粹由window组成.而是改成了window+view的组织模式.window是一个顶层窗口的概念.view就相当于在window内的控件.而subwindow则是依附于window ...
- TP常用函数
英文字符可用形如 {$vo.title|substr=0,5} 如果是中文字符thinkphp提供了msubstr如下 function msubstr($str, $start=0, $length ...
- 【OC语法快览】四、基础内存管理
Basic Memory Management 基础内存管理 If you're w ...
- 剑指 offer set 5 二进制中 1 的个数
总结 1. 负数右移会保持其符号. 比如 0x80000000 右移, 其对应的绝对值也是 0X80000000, 其右移一位并保持符号, 得到 0XC0000000. 符号位保持, 使得负数永远都无 ...
- IPC——命名管道
Linux进程间通信——使用命名管道 转载:http://blog.csdn.net/ljianhui/article/details/10202699 在前一篇文章——Linux进程间通信——使用匿 ...
- C#实现ByteBuffer类 .
在写网络程序的时候,经常需要往一个数组里面压数据或者取数据,而Java中再Java.nio中有个ByteBuffer能很方便的实现,Delphi中也有个Stream类有着同样的功能,这里我就模仿JAV ...