命令模式宏命令
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>命令模式宏命令</title> </head> <body> <script> var command1 = { execute: function(){ console.log(1); } }; var command2 = { execute: function(){ console.log(2); } }; var command3 = { execute: function(){ console.log(3); } }; // 定义宏命令,command.add方法把子命令添加进宏命令对象, // 当调用宏命令对象的execute方法时,会迭代这一组命令对象, // 并且依次执行他们的execute方法。 var command = function(){ return { commandsList: [], add: function(command){ this.commandsList.push(command); }, execute: function(){ for(var i = 0,commands = this.commandsList.length; i < commands; i+=1) { this.commandsList[i].execute(); } } } }; // 初始化宏命令 var c = command(); c.add(command1); c.add(command2); c.add(command3); c.execute(); // 1,2,3 </script> </body> </html>
命令模式的例子
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>命令模式</title> </head> <body> <button id="button1">刷新菜单目录</button> <button id="button2">增加子菜单</button> <button id="button3">删除子菜单</button> <script> var b1 = document.getElementById("button1"), b2 = document.getElementById("button2"), b3 = document.getElementById("button3"); // 定义setCommand 函数,该函数负责往按钮上面安装命令。点击按钮后会执行command对象的execute()方法。 var setCommand = function (button, command) { button.onclick = function () { command.execute(); } }; // 下面我们自己来定义各个对象来完成自己的业务操作 var MenuBar = { refersh: function () { alert("刷新菜单目录"); } }; var SubMenu = { add: function () { alert("增加子菜单"); }, del: function () { alert("删除子菜单"); } }; // 下面是编写命令类 var RefreshMenuBarCommand = function (receiver) { this.receiver = receiver; }; RefreshMenuBarCommand.prototype.execute = function () { this.receiver.refersh(); } // 增加命令操作 var AddSubMenuCommand = function (receiver) { this.receiver = receiver; }; AddSubMenuCommand.prototype.execute = function () { this.receiver.add(); } // 删除命令操作 var DelSubMenuCommand = function (receiver) { this.receiver = receiver; }; DelSubMenuCommand.prototype.execute = function () { this.receiver.del(); } // 最后把命令接收者传入到command对象中,并且把command对象安装到button上面 var refershBtn = new RefreshMenuBarCommand(MenuBar); var addBtn = new AddSubMenuCommand(SubMenu); var delBtn = new DelSubMenuCommand(SubMenu); setCommand(b1, refershBtn); setCommand(b2, addBtn); setCommand(b3, delBtn); </script> </body> </html>
四次挥手
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>四次挥手</title> </head> <body> <!-- 因为当服务端收到客户端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的, SYN报文是用来同步的。但是关闭连接时,当服务端收到FIN报文时,很可能并不会立即关闭SOCKET, 所以只能先回复一个ACK报文,告诉客户端,"你发的FIN报文我收到了"。只有等到我服务端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四次挥手。 --> </body> </html>
圣杯布局
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>圣杯布局</title> </head> <style> #container { padding-left: 200px; padding-right: 150px; overflow: auto; } #container p { float: left; } .center { width: 100%; background-color: lightcoral; } .left { width: 200px; position: relative; left: -200px; margin-left: -100%; background-color: lightcyan; } .right { width: 150px; margin-right: -150px; background-color: lightgreen; } .clearfix:after { content: ""; display: table; clear: both; } </style> <body> <!-- 三栏布局,中间一栏最先加载和渲染(内容最重要,这就是为什么还需要了解这种布局的原因)。 两侧内容固定,中间内容随着宽度自适应。 --> <div id="container" class="clearfix"> <p class="center">我是中间</p> <p class="left">我是左边</p> <p class="right">我是右边</p> </div> </body> </html>
在构造函数上定义方法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>原型和原型链</title> </head> <body> <script> //在构造函数上直接定义方法(不共享) // function Animai(){ // this.eat=function(){ // console.log("我爱吃饭") // } // } // let dog=new Animai() // let cat=new Animai() // dog.eat();//我爱吃饭 // cat.eat();//我爱吃饭 // console.log(dog.eat===cat.eat)//false //在原型上直接定义方法(共享) function Animai() { this.name = name } Animai.prototype.eat = function () { console.log('我爱吃饭', this.name) } let dog = new Animai() let cat = new Animai() dog.eat() //我爱吃饭 cat.eat() //我爱吃饭 console.log(dog.eat===cat.eat)//true </script> </body> </html>
垃圾清除机制
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <!-- 有两种垃圾回收策略: 标记清除:标记阶段即为所有活动对象做上标记,清除阶段则把没有标记(也就是非活动对象)销毁。 引用计数:它把对象是否不再需要简化定义为对象有没有其他对象引用到它。如果没有引用指向该对象(引用计数为 0),对象将被垃圾回收机制回收。 标记清除的缺点: 内存碎片化,空闲内存块是不连续的,容易出现很多空闲内存块,还可能会出现分配所需内存过大的对象时找不到合适的块。 分配速度慢,因为即便是使用 First-fit 策略,其操作仍是一个 O(n) 的操作,最坏情况是每次都要遍历到最后,同时因为碎片化,大对象的分配效率会更慢。 解决以上的缺点可以使用 **标记整理(Mark-Compact)算法 **,标记结束后,标记整理算法会将活着的对象(即不需要清理的对象)向内存的一端移动,最后清理掉边界的内存 引用计数的缺点: 需要一个计数器,所占内存空间大,因为我们也不知道被引用数量的上限。 解决不了循环引用导致的无法回收问题。 V8 的垃圾回收机制也是基于标记清除算法,不过对其做了一些优化。 针对新生区采用并行回收。 针对老生区采用增量标记与惰性回收。 --> </body> </html>