js的命名空间 && 单体模式 && 变量深拷贝和浅拷贝 && 页面弹窗设计
2017-08-25 10:47
686 查看
说在前面:这是我近期开发或者看书遇到的一些点,觉得还是蛮重要的。
一、为你的 JavaScript 对象提供命名空间
以上例子, jscbObject 提供了不同的命名空间,封装了函数 getElem() 、stripslashes() 、removeAngleBrackets(),防止和其他库的函数重名。其实很简单,很多人也写过类似的代码,但是不知道这种方式的含义。即使会写,面试的时候,不一定能答得出来“什么是命名空间?”。
二、单体模式
这个问题在C++、JAVA的面试题中都出现过。
好处:
1.可以用它来划分命名空间。
2.利用分支技术来封装浏览器之间的差异。
3.借助单体模式,可以把代码组织的更为一致,方便阅读与维护。
方法一:使用闭包
在该函数中使用var和function关键字分别来定义其私有属性和方法,这些在函数外部(单体对象外部)是无法直接访问的,因为函数一执行完毕,其内部作用域的空间就会被回收,这也就是能够利用闭包来模拟私有属性和方法的原因所在。在该函数(闭包)中,同时最终返回一个对象,这个对象中包含一些公有方法和属性,在外部可以直接调用,同时这些公有方法由于定义在函数内部,所以可以调用其私有属性和方法,但是外界只能通过返回的公有方法和属性来完成某些操作,不能够直接调用Singleton.privateMethod 和 Singleton.privateVariable 这些属性。这就使得该单体对象既隔离了外界去直接访问其私有属性和方法,又提供给外界一些共有属性和方法去完成某些操作。
js载入的时候就创建了这个对象。在单体模式中,针对一个对象只能创建一个实例。单体可以在一个特定的时间实例化,而不是作为一个解决方案中所定义的一个静态的构造而存在。上面示例中的单体使用一个立即调用的函数表达式(IIFE)将对象包装起来,IIFE会立即返回对象的一个实例。但是,不只是任何的实例,如果已经存在一个实例,它不会返回一个新的实例。这个特性在后续代码中得到了展示:
它返回了当时创建对象时候所生成的一个随机数,并且不管访问哪一个“实例”,都会返回相同的随机数。
方法二:对象字面量
这个单体对象的所有属性和方法都是共有的,外部可随时访问和修改。
三、js变量的深拷贝与浅拷贝
JS中的数据类型有:字符串、数字、布尔、数组、对象、Null、Undefined(Undefined 这个值表示变量不含有值,可以通过将变量的值设置为 null 来清空变量)。
对于字符串类型、数字、布尔的浅复制是对值的复制。对于数组和对象来说,浅复制是对对象地址的复制,并没有开辟新的栈,也就是复制的结果是两个对象指向同一个地址,修改其中一个对象的属性,则另一个对象的属性也会改变。而深复制则是开辟新的栈,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。
由以上示例可知,对于数据类型 “字符串、数字、布尔”,直接浅拷贝即可复制。对于数据类型“ 数组、对象”,若要复制变量的值,只能深拷贝。
网上找到一个很好的深拷贝方法:
可是在拷贝有些很复杂的对象的时候,会出现错误:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201708/25/72ded9701e34632420bf5d6a00bdcff3.png)
因为上述cloneObj() 中是用来递归,如果需要复制的 object 对象太大,递归次数太多导致内存被耗费太多,就会出现栈溢出的错误,这时候就得根据对象内容重新重新写clone()函数了。
可参考:http://blog.csdn.net/sysuzhyupeng/article/details/70340598
四、页面弹窗设计
弹窗1:警告框
弹窗2:确认框
弹窗3:提示框
弹窗4:模拟百度登录页面的弹窗
![](https://oscdn.geek-share.com/Uploads/Images/Content/201708/25/297b48dde0ef8fd8a74ae88569495dc9.png)
弹窗5:模拟客户端的可移动的功能弹窗
差不多是这样子
![](https://oscdn.geek-share.com/Uploads/Images/Content/201708/25/9bbc61f49af5d35984274501a65a45e2.png)
希望能帮到别人,喜欢就麻烦点个赞鼓励鼓励哈^_^
一、为你的 JavaScript 对象提供命名空间
<!DOCTYPE html> <html> <head> <title>为自己的js对象提供命名空间</title> </head> <body> <div>封装自己的数据和函数,防止和其他的库搞混了</div> <script> var jscbObject = { // return element getElem : function (identifier) { return document.getElementById(identifier); }, stripslashes : function(str) { return str.replace(/\\/g, ''); }, removeAngleBrackets: function(str) { return str.replace(/</g,'<').replace(/>/g,'>'); } }; var sample = "<div>testing\changes</div>"; var result = jscbObject.stripslashes(sample); result = jscbObject.removeAngleBrackets(result); console.log(result); //<div>testingchanges</div> </script> </body> </html>
以上例子, jscbObject 提供了不同的命名空间,封装了函数 getElem() 、stripslashes() 、removeAngleBrackets(),防止和其他库的函数重名。其实很简单,很多人也写过类似的代码,但是不知道这种方式的含义。即使会写,面试的时候,不一定能答得出来“什么是命名空间?”。
二、单体模式
这个问题在C++、JAVA的面试题中都出现过。
好处:
1.可以用它来划分命名空间。
2.利用分支技术来封装浏览器之间的差异。
3.借助单体模式,可以把代码组织的更为一致,方便阅读与维护。
方法一:使用闭包
<!DOCTYPE html> <html> <head> <title>什么是单例模式</title> </head> <body> <script> var mySingleton = (function () { // Instance stores a reference to the Singleton // 返回对象的引用 var instance; function init() {//创建实例的构造函数 // Singleton // Private methods and variables function privateMethod(){ console.log( "I am private" ); } var privateVariable = "Im also private"; var privateRandomNumber = Math.random(); return { // Public methods and variables publicMethod: function () { console.log( "The public can see me!" ); }, publicProperty: "I am also public", getRandomNumber: function() { return privateRandomNumber; } }; }; return { // Get the Singleton instance if one exists // or create one if it doesn't // 静态方法获得实例 getInstance: function () { if ( !instance ) { instance = init(); } return instance; } }; })(); singleA = mySingleton.getInstance(); var singleB = mySingleton.getInstance(); console.log( singleA.getRandomNumber() === singleB.getRandomNumber() ); //true </script> </body> </html>
在该函数中使用var和function关键字分别来定义其私有属性和方法,这些在函数外部(单体对象外部)是无法直接访问的,因为函数一执行完毕,其内部作用域的空间就会被回收,这也就是能够利用闭包来模拟私有属性和方法的原因所在。在该函数(闭包)中,同时最终返回一个对象,这个对象中包含一些公有方法和属性,在外部可以直接调用,同时这些公有方法由于定义在函数内部,所以可以调用其私有属性和方法,但是外界只能通过返回的公有方法和属性来完成某些操作,不能够直接调用Singleton.privateMethod 和 Singleton.privateVariable 这些属性。这就使得该单体对象既隔离了外界去直接访问其私有属性和方法,又提供给外界一些共有属性和方法去完成某些操作。
js载入的时候就创建了这个对象。在单体模式中,针对一个对象只能创建一个实例。单体可以在一个特定的时间实例化,而不是作为一个解决方案中所定义的一个静态的构造而存在。上面示例中的单体使用一个立即调用的函数表达式(IIFE)将对象包装起来,IIFE会立即返回对象的一个实例。但是,不只是任何的实例,如果已经存在一个实例,它不会返回一个新的实例。这个特性在后续代码中得到了展示:
singleA = mySingleton.getInstance(); var singleB = mySingleton.getInstance(); console.log( singleA.getRandomNumber() === singleB.getRandomNumber() ); //true
它返回了当时创建对象时候所生成的一个随机数,并且不管访问哪一个“实例”,都会返回相同的随机数。
方法二:对象字面量
var Singleton={ name: nimei, age: 2, walk: function(){ ... }, eat: function(){ ... } }
这个单体对象的所有属性和方法都是共有的,外部可随时访问和修改。
三、js变量的深拷贝与浅拷贝
JS中的数据类型有:字符串、数字、布尔、数组、对象、Null、Undefined(Undefined 这个值表示变量不含有值,可以通过将变量的值设置为 null 来清空变量)。
对于字符串类型、数字、布尔的浅复制是对值的复制。对于数组和对象来说,浅复制是对对象地址的复制,并没有开辟新的栈,也就是复制的结果是两个对象指向同一个地址,修改其中一个对象的属性,则另一个对象的属性也会改变。而深复制则是开辟新的栈,两个对象对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性。
<!DOCTYPE html> <html> <head> <title>浅拷贝与深拷贝</title> </head> <body> <script> var str1 = "Nice to meet you!"; var str2 = str1; str2 = 'He is called "Bill"'; console.log(" str1 " + str1 +" str2 " + str2); // str1 Nice to meet you! str2 He is called "Bill" var num1 = 1; var num2 = num1; num2 = 3; console.log(' num1 ' + num1 +" num2 " + num2); // num1 1 num2 3 var bool1 = true; var bool2 = bool1; bool2 = false; console.log(' bool1 ' +bool1 + " bool2 " + bool2); // bool1 true bool2 false var arr1 = ['one' , 'two' , 'three']; var arr2 = arr1; arr2[1] = 'change'; console.log(' arr1 ' + arr1 + " arr2 " +arr2); // arr1 one,change,three arr2 one,change,three var obj1 = { firstname : "Bill", lastname : "Gates", id : 5566 }; var obj2 = obj1; obj2.firstname = 'Bob'; console.log(' obj1.firstname ' + obj1.firstname + " obj2.firstname " + obj2.firstname); // obj1.firstname Bob obj2.firstname Bob </script> </body> </html>
由以上示例可知,对于数据类型 “字符串、数字、布尔”,直接浅拷贝即可复制。对于数据类型“ 数组、对象”,若要复制变量的值,只能深拷贝。
网上找到一个很好的深拷贝方法:
<!DOCTYPE html> <html> <head> <title>浅拷贝与深拷贝</title> </head> <body> <script> var cloneObj = function(obj){ var str, newobj = obj.constructor === Array ? [] : {}; if(typeof obj !== 'object'){ return; } else if(window.JSON){ str = JSON.stringify(obj), //系列化对象 newobj = JSON.parse(str); //还原 } else { for(var i in obj){ newobj[i] = typeof obj[i] === 'object' ? cloneObj(obj[i]) : obj[i]; } } return newobj; }; var arr1 = ['one' , 'two' , 'three']; var arr2 = cloneObj(arr1); arr2[1] = 'change'; console.log(' arr1 ' + arr1 + " arr2 " +arr2); // arr1 one,two,three arr2 one,change,three var obj1 = { firstname : "Bill", lastname : "Gates", id : 5566 }; var obj2 = cloneObj(obj1); obj2.firstname = 'Bob'; console.log(' obj1.firstname ' + obj1.firstname + " obj2.firstname " + obj2.firstname); // obj1.firstname Bill obj2.firstname Bob </script> </body> </html>
可是在拷贝有些很复杂的对象的时候,会出现错误:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201708/25/72ded9701e34632420bf5d6a00bdcff3.png)
因为上述cloneObj() 中是用来递归,如果需要复制的 object 对象太大,递归次数太多导致内存被耗费太多,就会出现栈溢出的错误,这时候就得根据对象内容重新重新写clone()函数了。
可参考:http://blog.csdn.net/sysuzhyupeng/article/details/70340598
四、页面弹窗设计
弹窗1:警告框
<!DOCTYPE html> <html> <head> <script> function myFunction() { alert("你好,我是一个警告框!");//方法一:alert } </script> </head> <body> <input type="button" onclick="myFunction()" value="显示警告框"> </body> </html>
弹窗2:确认框
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <p>点击按钮,显示确认框。</p> <button onclick="myFunction()">点我</button> <p id="demo"></p> <script> function myFunction(){ var x; var r=confirm("按下按钮!"); if (r==true){ x="你按下了\"确定\"按钮!"; } else{ x="你按下了\"取消\"按钮!"; } document.getElementById("demo").innerHTML=x; } </script> </body> </html>
弹窗3:提示框
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <p>点击按钮查看输入的对话框。</p> <button onclick="myFunction()">点我</button> <p id="demo"></p> <script> function myFunction(){ var x; var person=prompt("请输入你的名字","Harry Potter"); if (person!=null && person!=""){ x="你好 " + person + "! 今天感觉如何?"; document.getElementById("demo").innerHTML=x; } } </script> </body> </html>
弹窗4:模拟百度登录页面的弹窗
<!DOCTYPE html> <html> <head> <title>浅拷贝与深拷贝</title> <style type="text/css"> #mask { position:fixed; width: 100%; height: 100%; background-color: rgba(0,0,0,0.5); display: none; color: #888; } #win{ display:none; width: 300px; height: 700px; left: 35%; position: absolute; overflow: auto; background-color: #111; color: #888; } </style> </head> <body height = 100%> <div id="mask"></div> <div id="win"> <p>弹出窗口,父页面不可点击,只能操作弹出的页面,类似于百度的登录界面。可在弹出框页面加入表单、按钮等任何组件。</p> <button onclick = "closeWin()">隐藏</button> </div> <button onclick = "openWin()">弹出</button> <script> function openWin(){ document.getElementById("mask").style.display = "block"; document.getElementById("win").style.display = "block" } function closeWin(){ document.getElementById("mask").style.display = "none"; document.getElementById("win").style.display = "none" } </script> </body> </html>
![](https://oscdn.geek-share.com/Uploads/Images/Content/201708/25/297b48dde0ef8fd8a74ae88569495dc9.png)
弹窗5:模拟客户端的可移动的功能弹窗
<!DOCTYPE html> <html> <head> <title>浅拷贝与深拷贝</title> <style type="text/css"> #mask { position:fixed; height: 100%; background-color: rgba(0,0,0,0.5); display: none; color: #888; } #win{ display:none; width: 300px; height: 700px; left: 35%; position: absolute; overflow: auto; background-color: #111; color: #888; } </style> <script type="text/javascript" src="jquery-3.2.1.js"></script> <script type="text/javascript" src="jquery-ui.min.js"></script> </head> <body height = 100%> <div id="mask"></div> <div id="win"> <p>弹出窗口,父页面可点击,可同时操作父页面和弹出页面。可在弹出框页面加入表单、按钮等任何组件。</p> <button onclick = "closeWin()">隐藏</button> </div> <button onclick = "openWin()">弹出</button> <script> function openWin(){ document.getElementById("mask").style.display = "block"; document.getElementById("win").style.display = "block" } function closeWin(){ document.getElementById("mask").style.display = "none"; document.getElementById("win").style.display = "none" } $(function() { $( "#win" ).draggable(); }); </script> </body> </html>
差不多是这样子
![](https://oscdn.geek-share.com/Uploads/Images/Content/201708/25/9bbc61f49af5d35984274501a65a45e2.png)
希望能帮到别人,喜欢就麻烦点个赞鼓励鼓励哈^_^
相关文章推荐
- js的命名空间 && 单体模式 && 变量深拷贝和浅拷贝 && 页面弹窗设计
- Node.js global 变量 (全局命名空间!)
- C# 引用其他命名空间的公共变量时的警告:由于"***"是引用封送类的字段,访问上面的成员可能导致运行时异常
- PHP 面向对象编程和设计模式 (5/5) - PHP 命名空间的使用及名称解析规则
- js 用"name"做数组变量命名的问题
- 怎样让js不产生冲突,避免全局变量的泛滥,合理运用命名空间
- 设计模式-命名空间
- php 设计模式_命名空间的巧用
- php设计模式--命名空间与自动载入
- 理运用命名空间让js不产生冲突避免全局变量的泛滥
- 理运用命名空间让js不产生冲突避免全局变量的泛滥
- [js]设计模式小结&对原型的修改
- js设计模式--单体模式
- 使用单体模式设计原生js插件
- 设计算法并写出代码移除字符串中重复的字符,不能使用额外的缓存空间。注意: 可以使用额外的一个或两个变量,但不允许额外再开一个数组拷贝。
- 【js设计模式笔记---单体模式】
- JS(十六)继承模式,命名空间,对象枚举(下)
- Node.js 全局变量命名空间与命名空间中require模块的冲突
- JS小技巧-弹窗界面的js引用背景页面js中的变量。
- 【js设计模式笔记---单体模式】