转载地址http://blog.csdn.net/lmj623565791/article/details/34089553
javascript
今css
天重温了下Javacript,给你们带来一篇Javascript博文,相信对于Javacript有必定了解的人都听过prototype原型这个概念,今天咱们深度的分析下prototype与__proto__。html
好了,下面看一个很是简单的例子:html5
- var Person = function(name)
- {
- this.name = name ;
- };
- var p = new Person("Ben");
- console.log(p.name);
代码简单的 你不用说明了,若是如今让你们根据上面的代码画一张包含Function与Object的内存图,你们确定回想什么叫包含Function与Object,上面的代码和它们有几毛钱的关系。好了,下面我先按要求把图画出来,你们参考下:

解析下:java
一、任何一个由构造器产生的对象都有__proto__属性,且此属性指向该构造器的prototype。jquery
二、全部构造器/函数的__proto__都指向Function的prototypeandroid
拿第2条对比第1条,貌似咱们发现了什么,没错函数的构造器就是Function,看下面的代码:web
-
- var Person = function(name)
- {
- this.name = name ;
- };
-
- function Person(name)
- {
- this.name = name ;
- }
-
- var Person = new Function("name" , "this.name = name ;" );
固然了不能说说,下面看代码验证:
- console.log(Person.__proto__ === Function.prototype);
- console.log(typeof p.__proto__);
- console.log(p.__proto__.__proto__ === Object.prototype);
有人会问,那么Function与Object的prototype,__prop__究竟是什么呢?
- console.log(Object.__proto__ === Function.prototype);
- console.log(Function.__proto__ === Function.prototype);
- console.log(Function.prototype.__proto__ == Object.prototype);
- console.log(Object.prototype.__proto__);
有此可见ajax
一、全部的构造器包括Object和Function都继承了Function.prototype的方法,由第三行可知全部的构造器都是对象,即js中一切皆为对象。编程
二、__proto__最终的指向都是Object.prototype,这也就是js中的原型链。
最后咱们看一下Object的文档:
The following table lists properties of the Object Object.
发现Object还有个constructor属性。
一、constructor属性指向的是建立当前对象的构造函数。
二、每一个函数都有一个默认的属性prototype,而这个prototype的constructor默认指向这个函数
看下面的例子:
-
- var Person = function(name)
- {
- this.name = name ;
- };
-
- var p = new Person("Ben");
-
- console.log(p.constructor === Person);
- console.log(Person.prototype.constructor === Person);
- console.log(Person.prototype instanceof Object);
- console.log(Person.prototype instanceof Person);
-
- Person.prototype = {name:"123"} ;
- var p2 = new Person("Ben");
- console.log(p2.constructor === Object);
- console.log(p2.constructor === Person.prototype.constructor);
- console.log(Person.prototype.constructor === Object);
- console.log(Person.prototype.constructor === Person);
当改变Person的prototype时,会发现,Person.prototype.constructor指向了Object,主要是由于:
Person.prototype = {name:"123"} 至关于Person.prototype=new Object({name:"123"} );此时的构造器变成了Object.
好了,就介绍到这里,各位看官没事留个言,赞一个,哈~。
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/25076713
一直以为Js很强大,因为长期不写js代码,最近恰好温故温故。
一、Javascript没有代码块做用域的概念,局部做用域是针对函数来讲的。
二、若是不使用var声明的变量,默认为全局变量
三、Js中的做用域链
先看个简单的例子:只有一个函数对象,函数对象和其它对象同样,拥有能够经过代码访问的属性和一系列仅供JavaScript引擎访问的内部属性。其中一个内部属性是[[Scope]],由ECMA-262标准第三版定义,该内部属性包含了函数被建立的做用域中对象的集合,这个集合被称为函数的做用域链,它决定了哪些数据能被函数访问。
做用域链的图:

注:图中省略了,Global Scope中的window,document等,每一个函数对象中的arguments,this等均未画出。
观察上面代码,存在fun03,f,g三个函数对象。
下面是做用域链的图:

注:每一个函数对象一个做用域链,这里直接画在了一块儿;对于变量的查找,先从链的0开始找。
函数对象 f 在代码中执行了2 次,因此a*2*2 = 40 ; 函数对象 g 在代码中执行了1次, 因此 a *2 = 20 ;
四、闭包
上面的例子能够看到,在fun03执行完成后,a的实例并无被销毁,这就是闭包。我的对闭包的理解是:函数执行完成后,函数中的变量没有被销毁,被它返回的子函数所引用。
下面以一个特别经典的例子,同时使用做用域链解析:
相信上面的代码确定你们都写过,本意是点击每一个li,打印出它们的索引,但是事实上打印出的都是elements.length。这是为何呢?

看下上面的简易的做用域链(省略了不少部分,主要是理解),此时每一个onclick函数的i,指向的都是 onload 中的i 此时的 i = element.length.
下面看解决方案:
在onclick函数的外层,包了一层当即执行的函数,因此此时的n指向的 n 是当即执行的,全部都是1~elements.length 。
Javascript 进阶 封装
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/25080573
js中到处是对象,面向对象的第一步固然就是封装了,因为Js中没有类的概念,因此封装起来也比较麻烦,下面介绍两种js的封装。
一、使用约定优先的原则,将全部的私有变量以_开头
- <script type="text/javascript">
-
-
-
- var Person = function (no, name, age)
- {
- this.setNo(no);
- this.setName(name);
- this.setAge(age);
- }
- Person.prototype = {
- constructor: Person,
- checkNo: function (no)
- {
- if (!no.constructor == "string" || no.length != 4)
- throw new Error("学号必须为4位");
- },
- setNo: function (no)
- {
- this.checkNo(no);
- this._no = no;
- }, getNo: function ()
- {
- return this._no;
- }, setName: function (name)
- {
- this._name = name;
- }, getName: function ()
- {
- return this._name;
- }, setAge: function (age)
- {
- this._age = age;
- }, getAge: function ()
- {
- return this._age;
- }, toString: function ()
- {
- return "no = " + this._no + " , name = " + this._name + " , age = " + this._age;
- }
- };
- var p1 = new Person("0001", "鸿洋", "22");
- console.log(p1.toString());
- p1.setNo("0003");
- console.log(p1.toString());
- p1.no = "0004";
- p1._no = "0004";
- console.log(p1.toString());
-
- </script>
看完代码,是否是有种被坑的感受,仅仅把全部的变量以_开头,其实仍是能够直接访问的,这能叫封装么,固然了,说了是约定优先嘛,这种方式仍是不错的,最起码成员变量的getter,setter方法都是prototype中,并不是存在对象中,整体来讲仍是个不错的选择。若是你以为,这不行,必须严格实现封装,那么看第二种方式。
二、严格实现封装
看上面的代码,去掉了this.属性名,严格的实现了封装,只能经过getter,setter访问成员变量了,可是存在一个问题,全部的方法都存在对象中,增长了内存的开销。
三、以闭包的方式封装
- <script type="text/javascript">
-
-
-
-
- var Person = (function ()
- {
- var checkNo = function (no)
- {
- if (!no.constructor == "string" || no.length != 4)
- throw new Error("学号必须为4位");
- };
-
- var times = 0;
-
- return function (no, name, age)
- {
- console.log(times++);
- var no , name , age;
- this.setNo = function (no)
- {
- checkNo(no);
- this._no = no;
- };
- this.getNo = function ()
- {
- return this._no;
- }
- this.setName = function (name)
- {
- this._name = name;
- }
-
- this.getName = function ()
- {
- return this._name;
- }
-
- this.setAge = function (age)
- {
- this._age = age;
- }
- this.
- getAge = function ()
- {
- return this._age;
- }
-
- this.setNo(no);
- this.setName(name);
- this.setAge(age);
- }
- })();
- Person.prototype = {
- constructor: Person,
- toString: function ()
- {
- return "no = " + this._no + " , name = " + this._name + " , age = " + this._age;
- }
- }
- ;
- var p1 = new Person("0001", "鸿洋", "22");
- var p2 = new Person("0002", "abc", "23");
- var p3 = new Person("0003", "aobama", "24");
-
-
- console.log(p1.toString());
- console.log(p2.toString());
- console.log(p3.toString());
-
- </script>
上述代码,js引擎加载完后,会直接执行Student = 当即执行函数,而后此函数返回了一个子函数,这个子函数才是new Student所调用的构造函数,又由于子函数中保持了对当即执行函数中checkNo(no) ,times的引用,(很明显的闭包)因此对于checkNo和times,是全部Student对象所共有的,建立3个对象后,times分别为0,1,2 。这种方式的好处是,可使Student中须要复用的方法和属性作到私有且对象间共享。
一、基于类的继承
下面看下面的代码:
- <script type="text/javascript">
-
-
- function Person(name, age)
- {
- this.name = name;
- this.age = age;
- }
- Person.prototype.say = function ()
- {
- console.log(this.name + " , " + this.age);
- }
- function Student(no)
- {
- this.no = no;
- }
- <span style="white-space:pre">
-
- </span>
- Student.prototype = new Person();
- var stu1 = new Student("0001");
- stu1.name = '张三';
- stu1.age = '11';
- console.log(stu1.no);
- stu1.say();
-
-
- </script>
输出结果:
能够看到Student成功集成了Person,而且拥有了Person的say方法,核心代码其实就是一句 Student.prototype = new Person();,下面经过图解来讲明原理:

将Student.prototype指向new Person() , new Person的_proto_又指向Person Prototype;这样完成了整个继承。
可是这种方式存在问题:
问题1:当父类存在引用类型变量时,形成数据不一致,下面咱们给Person添加一个hobbies属性,类型为数组。
- <script type="text/javascript">
-
-
-
-
-
-
-
- function Person(name, age)
- {
- this.name = name;
- this.age = age;
- this.hobbies = [] ;
- }
- Person.prototype.say = function ()
- {
- console.log(this.name + " , " + this.age +" , " +this.hobbies);
- }
- function Student(no)
- {
- this.no = no;
- }
- Student.prototype = new Person();
-
- var stu1 = new Student("0001");
- stu1.name = '张三';
- stu1.age = '11';
- stu1.hobbies.push("soccer");
- stu1.say();
-
- var stu2 = new Student("0002");
- stu2.name = '李四';
- stu2.age = '12';
- stu2.hobbies.push("girl");
- stu2.say();
-
- </script>
输出结果:
- 张三 , 11 , soccer
- 李四 , 12 , soccer,girl
能够看出,李四的hobbies应该只有girl,可是上面的代码让全部对象共享了hobbies属性。
上述的继承方式还存在一个问题:
问题2:在Student的构造方法中,没法使用new Student("00001" , "张三" , 12) ;建立对象,并初始化name和age属性,必须stu.name, stu.age进行赋值
为了解决上述问题,对上述代码进行修改:
- <script type="text/javascript">
-
- function Person(name, age)
- {
- this.name = name;
- this.age = age;
- this.hobbies = [];
- }
- Person.prototype.say = function ()
- {
- console.log(this.name + " , " + this.age +" , " + this.hobbies);
- }
-
- function Student(name, age, no)
- {
-
-
-
-
- Person.call(this, name, age);
- this.no = no;
- }
-
- Student.prototype = new Person();
-
- var stu1 = new Student("0001","张三",11);
- stu1.hobbies.push("soccer");
- stu1.say();
-
- var stu2 = new Student("0002","李四",12);
- stu2.hobbies.push("cangjin");
- stu2.hobbies.push("basketball");
- stu2.say();
-
- </script>
输出:
- 0001 , 张三 , soccer
- 0002 , 李四 , cangjin,basketball
在Student的构造方法中使用了Person.call(this,name,age)感受就像super(name,age)【call的第一个参数为上下文】;而且成功解决了对引用属性的共享问题,完美解决。
二、基于原型链的继承
- <script type="text/javascript">
-
-
-
-
-
-
- var Person = {
- name: "人",
- age: 0,
- hobbies: [],
- say: function ()
- {
- console.log(this.name + " , " + this.age + " , " + this.hobbies);
- }
- }
- ;
-
- var Student = clone(Person);
- Student.no ="";
- Student.sayHello = function()
- {
- console.log(this.name +"hello ") ;
- }
-
- var stu1 = clone(Student);
- stu1.name = "zhangsan";
- stu1.age = 12;
- stu1.hobbies.push("Java");
- stu1.say();
-
- var stu2 = clone(Student);
- stu2.name = "lisi";
- stu2.age = 13;
- stu2.hobbies.push("Javascript");
- stu2.say();
-
-
-
-
-
-
- function clone(obj)
- {
- var F = function ()
- {
- };
- F.prototype = obj;
- return new F();
-
- }
-
-
- </script>
输出:
- zhangsan , 12 , Java
- lisi , 13 , Java,Javascript
能够看出一样存在引用属性不一致的问题,而且整个操做所有基于对象,给人的感受不是很好,下面经过图解解释下原理:

对象间经过一个clone函数,不断的返回一个新的对象,且prototype执行传入的对象,整个继承过程其实就是_proto_不断的指向,造成一个链,因此叫作原型链。
好了,已经介绍完了,js的两种集成的方式,最好使用的仍是经过类的继承(上述第一种方案,解决存在问题的)。
若是代码或者讲解存在任何问题,欢迎留言指出。
Javascript的难点就是面向对象编程,上一篇介绍了Javascript的两种继承方式:Javascript 进阶 继承,这篇使用一个例子来展现js如何面向对象编程,以及如何基于类实现继承。
一、利用面向对象的写法,实现下面这个功能,实时更新数据的一个例子:

二、使用对上面类的继承,完成下面的效果:

好了,很少说,js的训练全靠敲,因此若是以为面向对象不是很扎实,能够照着敲一个,若是以为很扎实了,提供了效果图,能够本身写试试。
一、第一个效果图代码:
-
-
-
-
-
-
-
-
-
-
-
-
-
- function PlaceFieldEditor(id, value, parentEle)
- {
- this.id = id;
- this.value = value;
- this.parentEle = parentEle;
- this.initValue = value ;
-
- this.initElements();
- this.initEvents();
- }
-
- PlaceFieldEditor.prototype = {
- constructor: PlaceFieldEditor,
-
-
-
- initElements: function ()
- {
- this.txtEle = $("<span/>");
- this.txtEle.text(this.value);
-
- this.textEle = $("<input type='text' />");
- this.textEle.val(this.value);
-
- this.btnWapper = $("<div style='display: inline;'/>");
- this.saveBtn = $("<input type='button' value='保存'/>");
- this.cancelBtn = $("<input type='button' value='取消'/>");
- this.btnWapper.append(this.saveBtn).append(this.cancelBtn);
-
- this.parentEle.append(this.txtEle).append(this.textEle).append(this.btnWapper);
-
- this.convertToReadable();
- },
-
-
-
- initEvents: function ()
- {
- var that = this;
- this.txtEle.on("click", function (event)
- {
- that.convertToEditable();
- });
-
- this.cancelBtn.on("click", function (event)
- {
- that.cancel();
- });
-
- this.saveBtn.on("click", function (event)
- {
- that.save();
- });
-
- },
-
-
-
- convertToEditable: function ()
- {
- this.txtEle.hide();
- this.textEle.show();
- this.textEle.focus();
-
- if(this.getValue() == this.initValue )
- {
- this.textEle.val("");
- }
-
- this.btnWapper.show();
- },
-
-
-
- save: function ()
- {
- this.setValue(this.textEle.val());
- this.txtEle.html(this.getValue().replace(/\n/g,"<br/>"));
-
- var url = "id=" + this.id + "&value=" + this.value;
-
- console.log(url);
- this.convertToReadable();
- },
-
-
-
- cancel: function ()
- {
- this.textEle.val(this.getValue());
- this.convertToReadable();
- },
-
-
-
- convertToReadable: function ()
- {
- this.txtEle.show();
- this.textEle.hide();
- this.btnWapper.hide();
- },
- setValue: function (value)
- {
- this.value = value;
- },
- getValue: function ()
- {
- return this.value;
- }
- }
- ;
引入到页面代码:
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <head>
- <title></title>
- <script type="text/javascript" src="jquery-1.8.3.js"></script>
- <script type="text/javascript" src="PlaceFieldEditor.js"></script>
-
- <script type="text/javascript">
- $(function ()
- {
-
- $("ul li").each(function ()
- {
- new PlaceFieldEditor($(this).attr("id"), "请输出成绩...", $(this));
- });
-
-
- });
-
- </script>
-
- <style type="text/css">
- body
- {
- font-size: 12px;
- color: #333;;
- }
-
- ul li
- {
- line-height: 30px;
- }
-
- </style>
- </head>
- <body>
-
-
- <ul>
- <li id="1">张三:</li>
- <li id="2">李四:</li>
- <li id="3">王二:</li>
- </ul>
-
- </body>
- </html>
嗯,代码就不详细说了,都比较简单,使用了jQuery,若是不喜欢可使用原生js,本人比较喜欢把jQuery看成js的工具使用。
二、第二个效果图的js代码:
-
-
-
-
-
-
-
- function PlaceAreaEditor(id, value, parentEle)
- {
- PlaceAreaEditor.superClass.constructor.call(this, id, value, parentEle);
- }
-
- extend(PlaceAreaEditor, PlaceFieldEditor);
-
- PlaceAreaEditor.prototype.initElements = function ()
- {
- this.txtEle = $("<span/>");
- this.txtEle.text(this.value);
-
- this.textEle = $("<textarea style='width:315px;height:70px;' />");
- this.textEle.text(this.value);
-
- this.btnWapper = $("<div style='display: block;'/>");
- this.saveBtn = $("<input type='button' value='保存'/>");
- this.cancelBtn = $("<input type='button' value='取消'/>");
- this.btnWapper.append(this.saveBtn).append(this.cancelBtn);
-
- this.parentEle.append(this.txtEle).append(this.textEle).append(this.btnWapper);
-
- this.convertToReadable();
-
- };
写了PlaceAreaEditor继承了PlaceFieldEditor,而后复写了initElements方法,改变了text为textarea。
extend的方法,上一篇博客已经介绍过:
-
-
-
-
- function extend(subClass, superClass)
- {
- var F = function ()
- {
- };
- F.prototype = superClass.prototype;
-
- subClass.prototype = new F();
-
- subClass.superClass = superClass.prototype;
- }
最后页面代码:
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
- "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <head>
- <title></title>
- <script type="text/javascript" src="jquery-1.8.3.js"></script>
- <script type="text/javascript" src="PlaceFieldEditor.js"></script>
- <script type="text/javascript" src="com.zhy.extend.utils.js"></script>
- <script type="text/javascript" src="PlaceAreaEditor.js"></script>
-
- <script type="text/javascript">
-
- $(function ()
- {
- $("ul li div").each(function ()
- {
- new PlaceAreaEditor($(this).attr("id"), "请留言...", $(this));
- });
- });
-
- </script>
-
- <style type="text/css">
-
- body
- {
- font-size: 12px;
- color: #333;;
- }
-
- ul li
- {
- padding: 5px 0 8px 0 ;
- }
-
- </style>
- </head>
- <body>
-
-
- <ul>
- <li id="1"><h3>我要改剧本,不让~~</h3>
- <div>
- </div>
- </li>
-
- <li id="2"><h3>悬崖上有桥么,有?没有~ </h3>
- <div>
- </div>
- </li>
- <li id="3"><h3>你敢打坏个人灯?不租~ </h3>
- <div>
- </div>
- </li>
- </ul>
-
- </body>
- </html>
好了,结束~~ 上面的例子是根据孔浩老师的例子修改的,感谢孔浩老师,孔老师地址:
www.konghao.org。
孔老师录制了不少Java相关视频,有兴趣的能够去他网站学习!
代码或者讲解有任何问题,欢迎留言指出。
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/30490955
一直很喜欢Js,,,今天写一个Js的单例模式实现以及用法。
一、单例模式的写法
单例模式写法至关简单:
- var singleTon = {
- m1: "memeber first ",
- m2: "memeber second ",
- f1: function ()
- {
- console.log("fun1 ");
- }
- };
好了,结束了,其实就是字面量建立对象的方式,很简单吧。若是你以为单例太简单,不用看了,那你就错了,单例在Js中用的地方挺多,话说你常常用么~。
二、单例用法一:建立命名空间
在开发中一个页面通常会引入多个Js文件,甚至这多个文件多人写的,你们均可能在全局定义init这个方法,均可能在全局声明name这是属性。这样的话就形成的命名的冲突,发生一些意想不到的问题。因此咱们须要引入命名空间:
咱们可让每一个程序猿写的Js在他本身的命名空间下:
-
-
-
-
- var ZhangHongYang = {};
-
- var zhy = {};
- zhy.com = {} ;
- zhy.com.js = {};
好比以每一个人的名字做为命名空间,以后写方法就:ZhangHongyang.xxx();或者你习惯了Java的命名空间,也能够zhy.com.js.xxx。
三、单例实例:实现一个注册页面的Js
针对像注册页面上的Js,通常都是针对此页面写的,建议使用单例的方式书写。
下面的展现如何使用单例的写法,实现ajax的注册功能,固然没有服务器,模拟一下:
html:
- <body>
- <form action="user/register" id="registerForm">
-
- <div>
- <label for="username">username</label>
- <input type="text" name="username" id="username"/>
- </div>
- <div>
- <label for="nickname">nickname</label>
- <input type="text" name="nickname" id="nickname"/>
- </div>
- <div>
- <label for="password">password</label>
- <input type="text" name="password" id="password"/>
- </div>
-
- <div>
- <input type="submit" value="Register"/>
- </div>
- </form>
-
- <div id="registerResult" style="width: 400px;height: 200px;border: 1px solid #444;">
-
- </div>
-
-
- </body>
当用户点击submit,会进行一些列的处理,最终将数据展现到registerResult中:
- <script type="text/javascript">
-
-
-
-
-
-
-
-
-
-
-
-
-
- ZhangHongYang.singlePageJsForRegister =
- {
- ID_FROM: "registerForm",
- ID_RESULT_CONTAINER: "registerResult",
- init: function ()
- {
- ZhangHongYang.singlePageJsForRegister.form = $("#" + this.ID_FROM);
- ZhangHongYang.singlePageJsForRegister.result = $("#" + ZhangHongYang.singlePageJsForRegister.ID_RESULT_CONTAINER);
- this.form.submit(this.handleSubmit);
- },
- handleSubmit: function (event)
- {
-
- var datas = {};
- ZhangHongYang.singlePageJsForRegister.form.find("input").each(function (i)
- {
-
- if (!($(this).attr("type") == "button" || $(this).attr("type") == "submit" || $(this).attr("type") == "reset" ))
- {
- datas[$(this).attr("name")] = $(this).val();
- }
- });
- ZhangHongYang.singlePageJsForRegister.ajaxSubmit(datas);
-
- event.preventDefault();
- },
- ajaxSubmit: function (datas)
- {
- var url = ZhangHongYang.singlePageJsForRegister.form.attr("action");
- console.log("url :" + url);
-
-
-
- ZhangHongYang.singlePageJsForRegister.showResult(datas);
- },
- showResult: function (datas)
- {
- var result = "";
- for (var p in datas)
- {
- result += p + " = " + datas[p] + "<br/>";
- }
- ZhangHongYang.singlePageJsForRegister.result.html(result);
- }
- };
-
- $(function ()
- {
- ZhangHongYang.singlePageJsForRegister.init();
- });
-
-
- </script>
咱们使用单例定义了一个singlePageJsForRegister方法对象,而后将须要用到的元素的Id做为了常量,而后经过init初始化事件等,还有其余的几个函数,代码中也书写了注释。看了上面的代码可能以为这么写好复杂,代码量也多了,可是对于Js的提高,要慢慢的学习面向对象以及结构化的写法,不能在script标签中,不断的定义各类方法,甚至在html标签中书写onclick这类的属性。Js必定要保证,html与js文件解耦;js代码总体上结构清晰;学习使用面向对象的方式处理问题。

四、如何在单例建立的对象中,定义私有方法和属性
上述单例的写法,会把全部的方法与变量暴露给使用者, 如何设置私有变量或者私有方法。
a、采用约定的方式:全部以_开头的方法和变量都是私有变量。
-
-
-
-
- var singleTon = {
- _m1: "hello",
- _f1: function ()
- {
- },
- init: function ()
- {
- }
- };
能够以为方式1不是本身骗本身么,可是项目嘛,约定因为配置,也是可行的。实在以为不能忍受,看方式二:
-
-
-
- var singleTon = (function ()
- {
- var _m1 = "hello";
- var _f1 = function ()
- {
- console.log(" i am a private function !");
- }
-
- return {
-
- init: function ()
- {
-
- _f1();
- }
- };
-
- })();
采用了闭包的方式,很好的实现了私有变量和私有方法的隐藏。
五、单例实例:解决Textarea的数据存储时的Html转Txt和展现时Txt转Html
在web项目中,不少状况会使用到Textarea。
a、好比留言、技能的书写等;对于这类Textarea咱们有必要对用户输入的html代码作特殊处理,防止用户填写恶意代码或者把页面的样式弄乱。
b、相反来讲,在Textarea中书写的换行以及空格,最终在div中显示却没有效果,都是一个空格,全部不少web开发者会选择使用只读textarea来回显用户输入内容,其实须要作必定的转换。
html:
- <body>
- <textarea style="width: 400px;height: 120px;" id="taContent">
- </textarea>
-
- <input type="button" id="convert" value="Convert"/>
- <br/>
- <br/>
-
-
- <fieldset style="width: 400px">
- <legend>html转化为Txt,供Div展现</legend>
- <div style="width: 400px;height: 120px;border: 1px solid #555;" id="divContent">
-
- </div>
- </fieldset>
-
- <br/>
- <br/>
-
- <fieldset style="width: 400px">
- <legend>Txt转化为Html,供Textarea修改</legend>
- <textarea style="width: 400px;height: 120px;" id="taEdit">
- </textarea>
- </fieldset>
-
- </body>
第一个Textarea用于用户输入,而后通过转义显示到div中,而后将转义后的数据进行逆向恢复显示到第二个TextArea中。至关与模拟了,div中展现数据和用户再次编辑数据,这些功能在项目中都至关实用。
咱们的js代码:
-
-
-
- ZhangHongYang.htmlFilter = (function ()
- {
-
-
-
-
-
- function _transSpace(data)
- {
- return data.replace(/\n/g, "<br/>").replace(/\s/g, " ");
- };
-
-
-
-
-
- function _transBrace(data)
- {
- return data.replace(/</g, "<").replace(/>/g, ">");
- };
-
-
- function _resumeSpace(data)
- {
- return data.replace(/ /g, " ").replace(/<br\s*\/>/ig, "\n");
- };
- function _resumeBrace(data)
- {
- return data.replace(/</g, "<").replace(/>/g, ">");
- };
-
- return {
-
- txt2Html: function (data)
- {
- return _transSpace(_transBrace(data));
-
- }, html2Txt: function (data)
- {
- return _resumeSpace(_resumeBrace(data));
- }
- };
-
- })();
在个人命名空间下定义了htmlFilter方法,而后最后暴露两个方法Html2Txt和Txt2Html给使用者。
调用的代码:
- <script type="text/javascript">
- $(function ()
- {
- $("#convert").click(function ()
- {
- var txt = ZhangHongYang.htmlFilter.txt2Html($("#taContent").val());
- console.log(txt);
- $("#divContent").html(txt);
- $("#taEdit").val(ZhangHongYang.htmlFilter.html2Txt(txt));
- });
- });
- </script>
效果图:

能够看到换行、空格、以及恶意的HTML代码等都获得了很好的在DIV中的显示;且最终可还原为Textarea中供编辑;若是各位项目中没有考虑到这类问题,首先你能够测试下问题,而后可使用上面的代码解决这类问题。
六、单例写法提升多分支代码效率
相信你们都了解过ajax,对象ajax确定离不开XMLHttpRequest,并且不一样版本、类型的浏览器建立方式不一致。通常咱们可能会这么写建立XMLHttpRequest的方法:
- function createXhr()
- {
- var xmlhttp;
- if (window.XMLHttpRequest)
- {
- xmlhttp=new XMLHttpRequest();
- }
- else
- {
- xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
- }
-
- return xmlhttp ;
- }
存在一个问题,每次建立XHR对象都须要进行分支判断,若是某个方法分支特别多,咱们能够作进一步的优化,当浏览器加载js文件时,就决定之后调用只会用其中合适的方式,而不会走分支。
咱们把代码改为:
-
-
-
- ZhangHongYang.xhrFactroy = (function ()
- {
- function _ieCreateXhr()
- {
- return new ActiveXObject("Microsoft.XMLHTTP");
- }
-
- function _newCreateXhr()
- {
-
- return new XMLHttpRequest();
- }
-
- if (window.XMLHttpRequest)
- {
- return _newCreateXhr;
- }
- else
- {
- return _ieCreateXhr;
- }
- })();
当程序加载完成js文件后,会自动根据浏览器类型返回适合的方法,避免每次都会进行分支判断,咱们只须要使用ZhangHongYang.xhrFactroy();建立XHR对象。
七、单例引入懒加载功能
上述的js的文件基本在引入页面后,浏览器加载就会进行大量操做占用内存,有时候咱们但愿等到咱们去使用时再去执行一些操做,若是从未使用就省去没必要要的内存消耗,咱们能够进行以下改写代码:
-
-
-
- ZhangHongYang.xhrFactroy = (function ()
- {
- var _instance = null;
-
- function _constructor()
- {
- function _ieCreateXhr()
- {
- return new ActiveXObject("Microsoft.XMLHTTP");
- }
-
- function _newCreateXhr()
- {
-
- return new XMLHttpRequest();
- }
-
- if (window.XMLHttpRequest)
- {
- return _newCreateXhr;
- }
- else
- {
- return _ieCreateXhr;
- }
- }
-
- return {getInstance: function ()
- {
- if (_instance == null)
- {
- _instance = _constructor();
- }
- return _instance;
-
- }};
-
- })();
- <script type="text/javascript">
-
- var xhrFactoryMethod = ZhangHongYang.xhrFactroy.getInstance();
- console.log(xhrFactoryMethod());
-
- </script>
只有使用时才会去执行_constructor()方法,而不是咱们以前的一加载完成就执行。
好了,js的单例模式已常常用的方法介绍完了,之后在书写js代码时,能够尝试使用上述的方法进行书写,而不是大量定义全局function以及变量,请不要在html标签中增长事件处理的代码~
若是存在任何问题,或者有任何问题请留言~
HTML5 CSS3 诱人的实例 :模仿优酷视频截图功能
通常的视频网站对于用户上传的视频,在用户上传完成后,能够对播放的视频进行截图,而后做为视频的展现图。项目中也能够引入这样的功能给用户一种不错的体验,而不是让用户额外上传一张展现图。
效果图:

看起来仍是很不错,下面我给你们分析下,极其核心代码很简单:
- _canvas = document.createElement("canvas");
- _ctx = _canvas.getContext("2d");
- _ctx.fillStyle = '#ffffff';
- _ctx.fillRect(0, 0, _videoWidth, _videoWidth);
- _ctx.drawImage(_video, 0, 0, _videoWidth, _videoHeight, 0, 0, _videoWidth, _videoHeight);
- var dataUrl = _canvas.toDataURL("image/png");
核心代码就这几行,利用了ctx.drawImage时,第一个参数能够为video对象,而后就是经过canvas拿到DataUrl,赋值给Img标签了。关键点就这些。
下面来看整个例子:
HTML:
- <!DOCTYPE html>
- <html>
- <head>
- <title></title>
- <meta charset="utf-8">
-
- <style type="text/css">
-
-
- html
- {
- overflow: hidden;
- }
-
- body
- {
- background-color: #999;
- }
-
- video
- {
- display: block;
- margin: 60px auto 0;
- }
-
- #shotBar
- {
- position: absolute;
- bottom: 5px;
- height: 120px;
- width: 98%;
- background-color: #000;
- box-shadow: -5px -5px 10px #fff;
- border-radius: 5px;
- padding: 2px;
- overflow: auto;
- }
-
- #shotBar img
- {
- border: 3px solid #fff;
- border-radius: 5px;
- height: 110px;
- width: 210px;
- margin-left: 4px;
- }
-
-
- </style>
-
- <script type="text/javascript" src="../../../jquery-1.8.3.js"></script>
-
- <script type="text/javascript" src="videoshot.js"></script>
-
- <script type="text/javascript">
-
- $(function ()
- {
- ZhangHongyang.click2shot.init();
- });
-
- </script>
-
-
- </head>
- <body>
-
-
- <video src="media/style.mp4" controls id="video">
- </video>
- <div id="shotBar">
- </div>
- </body>
- </html>
html和css都是至关简单的。
主要看Js的代码:
-
-
-
-
-
-
-
-
- var ZhangHongyang = {};
- ZhangHongyang.click2shot = (function ()
- {
- var _ID_VIDEO = "video";
- var _ID_SHOTBAR = "shotBar";
- var _videoWidth = 0;
- var _videoHeight = 0;
- var _canvas = null;
- var _ctx = null;
- var _video = null;
-
- function _init()
- {
- _canvas = document.createElement("canvas");
- _ctx = _canvas.getContext("2d");
- _video = document.getElementById(_ID_VIDEO);
-
-
- _video.addEventListener("canplay", function ()
- {
- _canvas.width = _videoWidth = _video.videoWidth;
- _canvas.height = _videoHeight = _video.videoHeight;
- console.log(_videoWidth + " , " + _videoHeight);
- _ctx.fillStyle = '#ffffff';
- _ctx.fillRect(0, 0, _videoWidth, _videoWidth);
- $("#" + _ID_SHOTBAR).click(_click2shot);
-
- _video.removeEventListener("canplay", arguments.callee);
- });
-
- }
-
- function _click2shot(event)
- {
- _video.pause();
- _ctx.drawImage(_video, 0, 0, _videoWidth, _videoHeight, 0, 0, _videoWidth, _videoHeight);
- var dataUrl = _canvas.toDataURL("image/png");
-
-
- var $imgBig = $("<img/>");
-
- $imgBig.width(_videoWidth).height(_videoHeight).css({position: "absolute", left: _video.offsetLeft, top: _video.offsetTop, width: _videoWidth + "px", height: _videoWidth + "px"}).attr("src", dataUrl);
- $("body").append($imgBig);
-
-
- var $img = $("<img>");
- $img.attr("src", dataUrl);
- $(this).append($img);
-
- var offset = _getOffset($img[0]);
- $img.hide();
-
- $imgBig.animate({left: offset.x + "px", top: offset.y + "px", width: $img.width() + "px", height: $img.height() + "px"}, 200, function ()
- {
- $img.attr("src", dataUrl).show();
- $imgBig.remove();
- _video.play();
- });
-
-
- }
-
-
-
-
-
-
-
- function _getOffset(elem)
- {
- var pos = {x: elem.offsetLeft, y: elem.offsetTop};
- var offsetParent = elem.offsetParent;
- while (offsetParent)
- {
- pos.x += offsetParent.offsetLeft;
- pos.y += offsetParent.offsetTop;
- offsetParent = offsetParent.offsetParent;
- }
- return pos;
- }
-
-
- return {init: _init}
-
- })();
须要注意的是,video.canplay事件中获取完属性和一些操做后,必定要removeEventLinstener,不然暂停播放会一直调用此方法。点击事件时,会暂停video,而后在video的位置生成一张图片,使用jquery动画移动到缩略图的位置,而后移除文档,缩略图显示,形成的动画效果。
获得图片以后的上传之类的操做,你们能够本身添加。还有很重要的一点:canvas.toDataURL("image/png");可能须要在服务器中访问才能正常使用,我把写好的页面拖到了tomcat中,你们能够随便启动个什么服务器,否则会报安全问题。
好了,若是这篇文章对你有帮助请顶一个,同时也欢迎你们留言~
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/34089553
今天给你们带来一个刮刮乐的小例子~基于HTML5 canvas的,有兴趣的能够改为android版本的,或者其余的~
效果图:

贴一张我中500w的照片,咋办啊,怎么花呢~

好了,下面开始原理:
一、刮奖区域两个Canvas,一个是front , 一个back ,front遮盖住下面的canvas。
二、canvas默认填充了一个矩形,将下面canvas效果图遮盖,而后监听mouse事件,根据mousemove的x,y坐标,进行擦出front canvas上的矩形区域,而后显示出下面的canvas的效果图。
很简单把~嘿嘿~
一、HTML文件内容:
- <!DOCTYPE html>
- <html>
- <head>
- <title></title>
- <meta charset="utf-8">
-
- <script type="text/javascript" src="../../jquery-1.8.3.js"></script>
- <script type="text/javascript" src="canvas2d.js"></script>
-
- <script type="text/javascript" src="GuaGuaLe2.js"></script>
-
- <script type="text/javascript">
-
- $(function ()
- {
- var guaguale = new GuaGuaLe("front", "back");
- guaguale.init({msg: "¥5000000.00"});
- });
- </script>
- <style type="text/css">
-
-
- body
- {
- background: url("s_bd.jpg") repeat 0 0;
- }
-
- .container
- {
- position: relative;
- width: 400px;
- height: 160px;
- margin: 100px auto 0;
- background: url(s_title.png) no-repeat 0 0;
- background-size: 100% 100%;
- }
-
- #front, #back
- {
- position: absolute;
- width: 200px;
- left: 50%;
- top: 100%;
- margin-left: -130px;
- height: 80px;
- border-radius: 5px;
- border: 1px solid #444;
- }
-
- </style>
-
- </head>
- <body>
-
- <div class="container"