Javascript面向对象研究心得

这段时间正好公司项目须要,须要改动fullcalendar日历插件,有机会深入插件源代码。正好利用这个机会,我也大致学习了下面JS的面向对象编程,感觉收获还是比較多的。

所以写了以下这篇文章希望跟大家探讨探讨JS的面向对象,本人资历尚浅,还望各位大神多多不吝赐教。

总述

如今的发展趋势是,JS越来越面向对象化。而JS本身并未像Java,C#等语言,实现了明显的继承,封装等,我们须要通过JS本身的方式来模拟这些面向对象的方式。

Jquery的一些东西
1.each方法:
    这是在js面向对象编程中十分经常使用的一种方式,each方法使dom结构循环变得简洁,它能够遍历数组,对象,json等
$(selector).each(function(index,element)) 或  $.each(selector,function(index,element))
调用样例:
 var arr1 = [ "aaa", "bbb", "ccc" ];      $.each(arr1, function(i,val){      alert(i);       //输出: 0,1,2alert(val);      //输出:aaa,bbb,ccc});  
參数selector能够是dom元素($("input:hidden")),json({ one:1, two:2, three:3})等等
当參数是json格式时,传入函数的index就变为了json元素的key

看下jQuery中的each实现(网络摘抄) 
    function (object, callback, args) {
//该方法有三个參数:进行操作的对象obj,进行操作的函数fn,函数的參数argsvar name, i = 0,length = object.length;if (args) {if (length == undefined) {for (name in object) {if (callback.apply(object[name], args) === false) {break;}}} else {for (; i < length;) {if (callback.apply(object[i++], args) === false) {break;}}}} else {if (length == undefined) {for (name in object) {if (callback.call(object[name], name, object[name]) === false) {break;}}} else {for (var value = object[0]; i < length &&  !== false; value = object[++i]) {}/*object[0]取得jQuery对象中的第一个DOM元素,通过for循环,得到遍历整个jQuery对象中相应的每一个DOM元素,通过 callback.call( value,i,value);将callback的this对象指向value对象,而且传递两个參数,i表示索引值,value表示DOM元素;当中callback是相似于 function(index, elem) { ... } 的方法。所以就得到 $("...").each(function(index, elem){ ... });*/}}return object;}来源: <a target=_blank href="http://www.cnblogs.com/xiaojinhe2/archive/2011/10/12/2208740.html">http://www.cnblogs.com/xiaojinhe2/archive/2011/10/12/2208740.html</a>
上述中,回调函数callback作为參数传入,callback.call(value, i, value)这部分实际上限制了callback传入时仅仅会使用i,value两个參数。
在把callback作为參数的函数中,会定义callback实际的參数列表,外部定义callback时,需遵循此參数列表,最经常使用的样例就是jqueryAJAX中,调用成功返回的success函数或error函数。

 
JS高级特性:
1.
    ===运算符
    
    || ,&& 运算符    
 
2.函数作为值进行參数传递
jquery的AJAX是函数作为值传递的好样例
js中的函数传递都是按值进行传递的,函数名就是对象的引用,它使得函数能够向不论什么对象一样作为參数进行传递,由于这一特性JS有了更大的灵活性。
我们能够定义带有函数參数的函数,限定传入函数的參数,而不限定对于參数的实现(callback的原理)
下图为研究fullcalendar插件时的,插件定义了对日历元素的遍历函数,对每一个元素的操作则作为callback函数传入,这样我们能够对不同元素操做的遍历进行复用
function segmentElementEach(segments, callback) { // TODO: use in AgendaView?for (var i=0; i<segments.length; i++) {var segment = segments[i];var element = segment.element;if (element) {callback(segment, element, i);}}
}

注意以下这样的时尚大气的使用方法,有点像接口,但更开放
// report the elements to the View, for general drag/resize utilitiessegmentElementEach(segments, function(segment, element) {reportEventElement(segment.event, element);});// attach mouse handlers//attachHandlers(segments, modifiedEventId);// call `eventAfterRender` callback for each eventsegmentElementEach(segments, function(segment, element) {trigger('eventAfterRender', segment.event, segment.event, element);});
4.JS boolean
    在JS编程中,尤其是面向对象编程,常常会向一些推断语句传入一些对象,如(fullcalendar插件中截取):
// the container where the initial HTML will be rendered.// If `doAppend`==true, uses a temporary container.var renderContainer = doAppend ? $("<div/>") : finalContainer;
在JS中,推断语句会将传入值转换成Boolean后推断
转换规则:
数据类型 转为true的值 转为false的值
Boolean true false
String 不论什么非空字符串 “”空字符串
Number 不论什么非零数值 0和NaN
Object 不论什么对象 null
Undefined n/a undefined

JS面向对象

1.argument对象 
在JavaScript的每个函数里存在一个上下文相关的名为arguments的变量,它的行于一数组,包括传给数的參数,这个对象存在于每个函数的上下文中。
  argument[0]表示函数调用时传入的第一个參数,argument[1]表示第二个參数,由此类推
   若改动argument的值,则相应的出入參数也跟着改动。
argument对象在JS模拟函数重载时有非常大的用处


2.this
在不论什么语言中,包含操作系统,上下文这个概念总是不可获取,我们能够把上下文理解成当前程序运行的环境。
在JS中,这个上下文通过this来实现,this总是指向当前工作的上下文对象。在全局环境中,this指向window对象。
在函数调用时,能够通过call和apply方法来改变函数运行的上下文对象,this就会指向新的对象。这在兴许的继承中也会提及。

关于this的訪问:
在这个样例中,在getNameFunc函数内部取到的this不是object对象的this,而是window全局对象,由于object.getNameFunc()实际返回函数名getNameFunc,这时,调用函数的环境变为了全局环境,this因此变成了window。
JS中,每一个函数调用时都会自己主动取得this和arguments两个特殊变量。
  1. <script type="text/javascript">
  2. var name = "The Window";
  3. var object = {
  4. name : "My Object",
  5. getNameFunc : function(){
  6. return function(){
  7. return this.name;
  8. };
  9. }
  10. };
  11. alert(object.getNameFunc()()); //"The Window"
  12. </script>




3.函数重载
JS与java,c#的面向对象语言不同,函数没有重载的概念,相同的函数名后面的会覆盖前面的(JS函数名就是个引用)。
而JS的重载则能够通过argument对象来实现,例如以下是从《Javascript 面向对象编程》一书中截取。
能够通过argument的length属性推断函数调用时的參数列表,结合typeof类型推断,能够实现函数的重载
//一个简单的用来发送消息的函数
function sendMessage( msg, obj ) {
//假设同一时候提供了一个消息和一个对象
if ( arguments.length == 2 )
//就将消息发给该对象
obj.handleMsg( msg );
else	//否则,刚假定仅仅有消息被提供//于是显示该消息
alert( msg );
}

4.JS作用域
JS作用域以函数为界限,而没有块约束(for,if,while等),所以在for中定义的var变量实际上在for循环外部依旧起作用。
注意:在函数内部未使用varkeyword产生的变量,可在全局訪问

5.闭包
简单的说,闭包就是内层函数引用外层变量的手段,而外层则无法訪问内层的变量,是否闭包是对外层变量的封装,函数是否作为隔离之用?(在函数的生命周期内,外层无法影响变量)
结合《Javascript 面向对象编程》和 网上找的各种资料,我总结了闭包的下面几种使用方法。

(1)简单的封装函数,把实现业务的代码和參数分开,避免混乱的代码调用方式。
    下面为演示样例代码(取自:《Javascript 面向对象编程》
//用来延迟显示消息的通用函数
function delayedAlert( msg, time ) {
//初始化一个被封套的函数
setTimeout(function(){
//此函数使用了来自封套它的函数的变量msg
alert( msg );
}, time );
}
实本人感觉,这好像并没体现出闭包的什么特点,倒反而像是简单的封装
(2)匿名自运行函数
    在JS编写过程中,经常会在全局存放非常多变量,包含非常多暂时变量,这经常会对其它的函数造成影响,使用闭包能够解决这一问题。
    下面样例来自 http://blog.csdn.net/sunlylorn/article/details/6534610
  1. var datamodel = {
  2. table : [],
  3. tree : {}
  4. };
  5. (function(dm){
  6. for(var i = 0; i < dm.table.rows; i++){
  7. var row = dm.table.rows[i];
  8. for(var j = 0; j < row.cells; i++){
  9. drawCell(i, j);
  10. }
  11. }
  12. //build dm.tree
  13. })(datamodel);
我们无需去维护函数中的变量,运行结束后内部变量会被释放,而不会影响到全局(避免污染)

(3)设计模式中的单例模式
在single以外是无法訪问unique的,而且採用匿名函数,仅仅能初始化一次
  1. var single = (function(){
  2. var unique;
  3. function Construct(){
  4. // ... 生成单例的构造函数的代码
  5. }
  6. unique = new Constuct();
  7. return unique;
  8. })();
  9. 来源: <http://blog.chinaunix.net/uid-26672038-id-3886959.html>
(4)模拟面向对象类模板
  1. function Person(){
  2. var name = "default";
  3. return {
  4. getName : function(){
  5. return name;
  6. },
  7. setName : function(newName){
  8. name = newName;
  9. }
  10. }
  11. };
  12. var john = Person();
  13. print(john.getName());
  14. john.setName("john");
  15. print(john.getName());
  16. var jack = Person();
  17. print(jack.getName());
  18. jack.setName("jack");
  19. print(jack.getName());
  20. 执行结果例如以下:
  21. default
  22. john
  23. default
  24. jack
  25. 来源:http://blog.csdn.net/sunlylorn/article/details/6534610
(5)提供引用变量的创建值,而非其它变化后的值
//id为"main"的一个元素
var obj = document.getElementById("main");
//用来绑定的items数组
var items = [ "click", "keypress" ];
//遍历items中的每一项
for ( var i = 0; i < items.length; i++ ) {
//用自运行的匿名函数来激发作用域(function(){
//在些作用域内存储值var item = items[i];
//为obj元素绑定函数obj[ "on" + item ] = function() {
//item引用一个父级的变量,
//该变量在此for循环的上文中已被成功地scoped(?)alert( "Thanks for your " + item );};})();
}
  1. 4.JS中方法訪问范围
(1)共同拥有方法
介绍之前先说下prototype的概念。
prototype是全部JS对象共同拥有的构造对象。prototype本身也是对象,能够给其附加方法,属性,prototype加入的方法,属性全部主对象的实例共享。
(2)私有方法
全部函数内部定义的属性,方法,未绑定到this上下文对象的,在函数外部是无法訪问到的,样例例如以下:
  1. function Person(){
  2.  //都是私有的
  3. var name;
  4. function move(){
  5.  
  6. }
  7. }
(3)成员方法(本人类比java,c#等语言,姑且叫他成员方法)
  1. function Person(name){
  2. var name;
  3. function moveUp(){
  4. alert(name+" move");
  5. }
  6. this.moveUp = moveUp;
  7. }
  8. var jack = new Person("jack");
  9. jack.moveUp();
(4)通过成员方法訪问变量,如上例訪问name

(5)静态方法
静态方法类似于java等语言,能够直接通过累訪问。
JS中的静态方法,实际能够看做函数对象的属性,而不是通过函数对象创建出的对象的属性。所以无法通过事实上例訪问函数对象。


5.构造(重要)
在JS中,创建对象有多种方式,相比java等语言比較灵活。
JS中,能够先创建Object的实例,再为其加入属性和方法(不展演示样例子,比較简单),或通过字面量的方式(大括号包裹属性和方法)。
可是,用上述的基本方式创建对象会产生大量反复代码。下面几种方式是比較推荐的方式。
(1)工厂模式
作为最经常使用的设计模式之中的一个,在JS中相同能够模拟这样的方式。工厂模式用函数封装创建对象的细节,仅仅须要通过接口来创建对象。
  1. function createPerson(name, age, job){
  2. var o = new Object();
  3. o.name = name;
  4. o.age = age;
  5. o.job = job;
  6. o.sayName = function(){
  7. alert(this.name);
  8. };
  9. return o;
  10. }
  11. var person1 = createPerson("Nicholas", 29, "Software Engineer");
  12. var person2 = createPerson("Greg", 27, "Doctor");
  13. person1.sayName(); //"Nicholas"
  14. person2.sayName(); //"Greg"
  15. 来源:《Javascript 高级程序设计》
(2)构造函数
    在java,c#等面向对象语言中,这是非经常见的。
  1. function Person(name){
  2. var name;
  3. function moveUp(){
  4. alert(name+" move");
  5. }
  6. this.moveUp = moveUp;
  7. }
  8. var jack = new Person("jack");
  9. jack.moveUp();
(3)原型Prototype模式
我们创建的每一个函数,都有一个Prototype属性,该属性是个指针,指向一个用于包括特定类型全部实例共享属性和方法的对象。
每一个构造函数都会有一个原型对象(指向原型对象的指针),而通过构造函数构造出的对象相同有指向相同原型对象的指针,这也是后面可以通过原型链实现继承的基础

(4)静态方法创建
静态方法类似于java等语言,能够直接通过累訪问。
JS中的静态方法,实际能够看做函数对象的属性,而不是通过函数对象创建出的对象的属性。所以无法通过事实上例訪问函数对象。


6.继承(重要)
这里,我仅仅介绍最主要的几种集成方式,一些基于设计模式的扩展,这里就不做赘述了。
(1)原型链法
    通过子类的原型对象引用父类的实例对象,该实例对象将引用父类原型对象,从而实现了原型链。
原型链的最上一级一定是Object对象。

原型链搜索机制:读取时,从实例对象開始,顺着原型链一直向上搜索,若找不到属性或方法,则会在最后一步停止。
  1. function SuperType(){
  2. this.property = true;
  3. }
  4. SuperType.prototype.getSuperValue = function(){
  5. return this.property;
  6. };
  7. function SubType(){
  8. this.subproperty = false;
  9. }
  10. //inherit from SuperType
  11. SubType.prototype = new SuperType();
  12. SubType.prototype.getSubValue = function (){
  13. return this.subproperty;
  14. };
  15. var instance = new SubType();
  16. alert(instance.getSuperValue()); //true
对于原型链法,我有一点疑问,为何子类指向父类原型实例而非原型本身,希望能有高人给与指点

(2)借用构造函数
这是我所见过的最经常使用的方式,其思想是在子类中调用超类的构造函数,主要通过借助apply和call方法,即用子类的this环境去调用超类的构造函数,实现将超类的属性,方法拷贝到子类的过程。这在fullcalendar插件中大量使用。
  1. //下面是fullcalendar插件中穿件日历基础对象时继承事件处理类型EventManager的过程,t是用来存储this变量的,防止
  2.         //切换对结果的影响this
  3. // Imports
  4. // -----------------------------------------------------------------------------------
  5. EventManager.call(t, options);
  6. var isFetchNeeded = t.isFetchNeeded;
  7. var fetchEvents = t.fetchEvents;
兴许有心的东西还会有所补充

转载于:https://www.cnblogs.com/mengfanrong/p/3868798.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/460218.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

矩阵连乘积 ZOJ 1276 Optimal Array Multiplication Sequence

题目传送门 1 /*2 题意&#xff1a;加上适当的括号&#xff0c;改变计算顺序使得总的计算次数最少3 矩阵连乘积问题&#xff0c;DP解决&#xff1a;状态转移方程&#xff1a;4 dp[i][j] min (dp[i][k] dp[k1][j] p[i-1] * p[k] * p[j]) (i<k<j)5 s…

md5加密java实现_MD5加密(java实现)

java实现MD5加密:import java.security.MessageDigest;import sun.misc.BASE64Encoder;public class Tools {/** md5加密算法* return:结果为16进制的字符串长度为32位*/public static String getMd5String(String str) throws Exception{StringBuilder md5Code new StringBui…

POJ 1273 Drainage Ditches 最大流

很裸的最大流问题&#xff0c;不过注意会有重边&#xff0c;o(╯□╰)o&#xff0c;被阴了WA了一发 还有就是要用long long #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <stri…

java语言 编译原理_【Java学习】深入分析Java的编译原理

在《Java代码的编译与反编译》中&#xff0c;有过关于Java语言的编译和反编译的介绍。我们可以通过javac命令将Java程序的源代码编译成Java字节码&#xff0c;即我们常说的class文件。这是我们通常意义上理解的编译。但是&#xff0c;字节码并不是机器语言&#xff0c;要想让机…

javaSE_base04_集合框架

四、集合框架1&#xff1a;String类&#xff1a;字符串(重点) (1)多个字符组成的一个序列&#xff0c;叫字符串。 生活中很多数据的描述都采用的是字符串的。而且我们还会对其进行操作。 所以&#xff0c;java就提供了这样的一个类供我们使用。 (2)创建字…

火狐浏览器中打开java_将Firefox浏览器嵌入Java Swing中

小编典典这是一些示例代码import java.awt.Color;import java.awt.Component;import java.awt.Container;import java.awt.FlowLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.FileNotFoundException;import java.io.File;imp…

实验 使用 vivado zedboard GPIO 开关 开控制 LED

前面我做了几个实验 都没有用过 开关&#xff0c;这一次用一用 发现 vivado 真的挺方便 所以 使用 vivado 开发 1.建工程 我使用 vivado 2013.4 创建新工程 –》 next –》next 勾选 Do not specify sources at this time //这样跳过后面两个添加文件页面 选择 board –》 ze…

java 最优化_java-多维度求最优解

拿出11条数据//条件每个位置(position)的人数限制每队(team)人数不能超过7人credits的总和在100分之内(包含100)总分(points)最高//位置人数限制position-1 : 1 position-2 : 3-5 position-3 : 1-3 position-4 : 3-5//模拟数据{points credits position team56 9.0 1 t154 9.1 …

polymer web componets 大前端

大前端 东南水乡 一叶小舟拂过水面 船上两位大侠把酒言欢 一位是玉真人 另一位是张真人 两人喝到开心处 变作对联起来 上联 前端研究&#xff0c;研究个屁~ 下联 前端设计&#xff0c;设计个屁~ 横批 前端sb特色 polymer 提供创建自定义和标准dom元素类似的自定义元素功能 可以…

citespace安装如何配置JAVA_citespace超详细安装教程

想用citespace写篇量化的文献综述但是试了很多次一直运行不了&#xff0c;无奈因为要分析的论文太多&#xff0c;只能继续学着下载……在踩了很多坑之后终于搞定了&#xff01;&#xff01;我参考了知乎大神们写的学习指南&#xff0c;但在下载过程中还是会遇到一点点小问题&am…

Ubuntu下安装配置JDK

第一步&#xff1a;下载jdk-7-linux-i586.tar.gz wget -c http://download.oracle.com/otn-pub/java/jdk/7/jdk-7-linux-i586.tar.gz 若失败&#xff0c;则自行下载即可。 第二步&#xff1a;解压安装 sudo tar zxvf ./jdk-7-linux-i586.tar.gz -C /usr/lib/jvm cd /usr/lib/…

必应(Bing)每日图片获取API

必应(Bing)每日图片获取API January 11, 2015 API http://lab.dobyi.com/api/bing.php 介绍 ValueDescriptiontitle标题desc描述url图片地址你们自由发挥……

java取模多位数_JAVA大数类—基础操作(加减乘除、取模、四舍五入、设置保留位数)...

当基础数据类型长度无法满足需求时可以使用大数类构造方法接受字符串为参数1 BigInteger bInt new BigInteger("123123");2 BigDecimal bDouble new BigDecimal("123123.123123124");基础操作(取模使用divideAndRemainder方法&#xff0c;返回的数组第二…

HDU 4902

数据太弱&#xff0c;直接让我小暴力一下就过了&#xff0c;一开始没注意到时间是15000MS&#xff0c;队友发现真是太给力了 #include <cstdio> #include <cstring> int n,q,a[100005],x[100005],p,l[100005],r[100005],t[100005]; int tree[1000005]; void build(…

tcp/udp高并发和高吐吞性能测试工具

在编写一个网络服务的时候都比较关心这个服务能达到多少并发连接,而在这连接的基础上又能达到一个怎样的交互能力.编写服务已经是一件很花力气的事情,而还要去编写一个能够体现结果的测试工具就更加消耗工作时间.下面介绍一个测试工具只需要简单地设置一下就能对tcp/udp服务进行…

java socket 对方关闭_java Socket判断对方是否已关闭连接

如何判断远端socket是否已经断开连接&#xff0c;如果断开那么需要重新连接。1通过socket类的方法isClosed()、isConnected()、isInputStreamShutdown()、isOutputStreamShutdown()等&#xff0c;这些方法都是本地端的状态&#xff0c;无法判断远端是否已经断开连接。2通过Outp…

几个数字的和

ctrl z 的使用 #include<iostream> using namespace std;main() {int num,sum0;while(cin>>num) {sumnum;}cout<<"和为"<<sum<<endl; } View Code#include<iostream> using namespace std; main() { int num,s…

sharepoint 2013基于AD的Form表单登录(三)——选择用户时,屏蔽掉AD。

//来源&#xff1a;http://www.cnblogs.com/lrforever/p/3695820.html 隐藏AD人员选择&#xff0c;$ad.IsVisible设置为true&#xff0c;则显示出AD里用户$cpm Get-SPClaimProviderManager $ad get-spclaimprovider -identity "AD" $ad.IsVisible $false $cpm.Up…

java synchronized boolean_java中synchronized关键字

代码示例&#xff1a;package com.test;/** x,y值为什么不能保持相同&#xff1b;**/public class Pair implements Runnable{boolean b false;private int x;private int y;public Pair(int x,int y){this.x x;this.y y;}public Pair(){}public void incrementX(){x;}publi…

网站在线压力测试工具Load Impact

关于Load ImpactLoad Impact是一个一个在线的网站压力测试服务及工具&#xff0c;模拟多用户同时访问你的站点&#xff0c;并出具报告以分析你的站点可以支撑的访问者数量&#xff0c;它能让你通过简单的几次点击就能测试出你的网站的性能。不过免费用户只能同时并发50个虚拟访…