前端小知识点扫盲笔记记录7 您所在的位置:网站首页 chromechrome浏览器 前端小知识点扫盲笔记记录7

前端小知识点扫盲笔记记录7

2023-04-13 18:12| 来源: 网络整理| 查看: 265

前端小知识点扫盲笔记记录7 原创

前端歌谣 2023-04-12 14:30:47 ©著作权

文章标签 html 构造函数 缓存 文章分类 JavaScript 前端开发 yyds干货盘点

©著作权归作者所有:来自51CTO博客作者前端歌谣的原创作品,请联系作者获取转载授权,否则将追究法律责任 前言

我是歌谣 放弃很容易 但是坚持一定很酷 微信公众号关注前端小歌谣带你进入前端巅峰交流群 今天继续对前端知识的小结

单体模式应用弹框 单体模式应用弹框 我是歌谣 // 实现单体模式弹窗 var createWindow = (function () { var div; return function () { if (!div) { div = document.createElement("div"); div.innerHTML = "我是弹窗内容"; div.style.display = 'none'; document.body.appendChild(div); } return div; } })(); document.getElementById("Id").onclick = function () { // 点击后先创建一个div元素 var win = createWindow(); win.style.display = "block"; } 原型和原型链 原型和原型链 // 对象可以使用构造函数prototype原型对象的属性和方法,就是因为对象有__proto__原型的存在 // 每个对象都有__proto__原型的存在 //// 原型的构造器指向构造函数。 //原型上添加方法注意的地方 构造器指向构造函数本身 //Star.prototype = {}给原型重新赋值,此时会丢失构造器, //我们需要手动定义构造器,指回构造函数本身 // 原型的构造器指向构造函数。 function Animal(name) { this.name = name } let obj = new Animal('小猴') console.log(Animal.prototype.constructor === Animal) //true console.log(obj.__proto__.constructor === Animal) //true //原型上添加方法注意的地方 构造器指向构造函数本身 function Star(name) { this.name = name } Star.prototype.dance = function () { console.log(this.name) } let geyao = new Star('小花') console.log(geyao.__proto__) //{dance: ƒ, constructor: ƒ} console.log(geyao.__proto__.constructor) // Star //赋值{} function Star(name) { this.name = name } Star.prototype = { dance: function () { console.log(this.name) }, } let fangfang = new Star('小红') console.log(fangfang.__proto__) //{dance: ƒ} console.log(fangfang.__proto__.constructor) // ƒ Object() { [native code] } Star.prototype.constructor = Star 原型和原型链继承方式 原型继承方式 //ES6之前并没有给我们提供extends继承,我们可以通过构造函数+原型对象模拟实现继承。 // 继承属性,利用call改变this指向。但该方法只可以继承属性,实例不可以使用父类的方法。 // function Father(name) { // this.name = name // } // Father.prototype.dance = function () { // console.log('我会跳舞') // } // function Son(name, age) { // Father.call(this, name) // this.age = age // } // let son = new Son('歌谣', 100) // son.dance() //报错 // 解决方法1:利用Son.prototype = Father.prototype改变原型指向,但此时我们给子类增加原型方法,同样会影响到父类。 // function Father(name) { // this.name = name // } // Father.prototype.dance = function () { // console.log('我会跳舞') // } // function Son(name, age) { // Father.call(this, name) // this.age = age // } // Son.prototype = Father.prototype // //为子类添加方法 // Son.prototype.sing = function () { // console.log('我会唱歌') // } // let son = new Son('歌谣', 100) // //此时父类也被影响了 // console.log(Father.prototype) //{dance: ƒ, sing: ƒ, constructor: ƒ} //解决方法2:子类的原型指向父类的实例,这样就可以顺着原型链共享父类的方法了。并且为子类添加原型方法的时候,不会影响父类。 function Father(name) { this.name = name } Father.prototype.dance = function () { console.log('我会跳舞') } function Son(name, age) { Father.call(this, name) this.age = age } Son.prototype = new Father() Son.prototype.sing = function () { console.log('我会唱歌') } let son = new Son('歌谣', 100) console.log(Father.prototype) //{dance: ƒ, constructor: ƒ} 原型式继承 原型式继承 //方法等同于Object.create() //返回原来的原型对象 function object(obj) { function F() {} F.prototype = obj return new F() } //利用一个空对象作为中介,将某个对象直接赋值给空对象构造函数的原型。 var person = { name: 'Nicholas', friends: ['Shelby', 'Court', 'Van'], } var anotherPerson = object(person) anotherPerson.name = 'Greg' anotherPerson.friends.push('Rob') var yetAnotherPerson = object(person) yetAnotherPerson.name = 'Linda' yetAnotherPerson.friends.push('Barbie') //原型链继承多个实例的引用类型属性指向相同,存在篡改的可能。 // 无法传递参数 console.log(person.friends) //"Shelby,Court,Van,Rob,Barbie" 双飞翼布局 双飞翼布局220402 .float { float: left; } #main { width: 100%; height: 200px; background-color: lightpink; } #main-wrap { margin: 0 190px 0 190px; } #left { width: 190px; height: 200px; background-color: lightsalmon; margin-left: -100%; } #right { width: 190px; height: 200px; background-color: lightskyblue; margin-left: -190px; } main left right 发布-订阅者模式例子 发布--订阅者模式 ////定义一所学校(中间件,事件派发中心) //主要功能包括校园网(topics),以及学生订阅消息(subscribe),老师发布课程(publish) let School = { type: "hunt", topics: Object.create(null), //添加订阅的事件,当一个对象订阅事件的时候,分别传入事件名字和回调函数(当订阅事件触发时候执行的操作) subscribe: function (topic, fn) { //如果派发对象内检索不到这个对象,就说明是一个新事件,新建一个数组对象,然后把该订阅者的回调放进事件对象中 //topics是一个对象,里面有多个事件对象,事件对象内部是一个数组,包含这个事件的订阅者 if (!this.topics[topic]) { this.topics[topic] = []; console.log("添加订阅" + topic + "的学生到Peter老师的订阅对象中"); this.topics[topic].push(fn); } }, // 发布事件,在事件订阅对象中检索这个事件,有就调用该对象中所有回调,否则直接返回 publish: function (topic, money) { if (!this.topics[topic]) return; for (let fn of this.topics[topic]) { console.log("校园网发布" + topic + "课程"); fn(money); } } } //定义一个师生类 //包括姓名,身份 function Student(name, identity) { this.name = name; this.identity = identity; //师生可以在校园网上发布订阅任务 //定义一个订阅函数,这里面调用了任务中心的订阅函数,收集所有订阅者的订阅事件和回调 this.subscribe = function subscribe(topic, fn) { console.log(this.identity + "的" + this.name + "在校园网订阅了" + topic + "的课程"); School.subscribe(topic, fn); }; //定义一个发布函数,这里面调用了任务中心的发布函数,调用所有订阅者的回调 this.publish = function publish(topic, money) { console.log(this.identity + "老师" + this.name + "在校园网发布了" + topic + "的课程"); School.publish(topic, money); }; } //案例开始,先定义学生,老师 let studentMing = new Student("小明", "大一"); let studentJin = new Student("小金", "大一"); let studentZhang = new Student("小张", "大一"); let studentPeter = new Student("Peter", "老师"); //小明,小金,小张分别订阅了发布课程 studentMing.subscribe("Peter老师", function (money) { console.log("小明表示:" + (money = "美术课" ? "不" : "") + "接取美术课"); }); studentJin.subscribe("Peter老师", function (money) { console.log("小金表示:接取任何课程"); }); studentZhang.subscribe("Peter老师", function (money) { console.log("小张表示:" + (money = "前端课" ? "我不上其他课," : "") + "我要上前端课啊"); }); //Peter发布了课程,美术课 studentPeter.publish("Peter老师", "美术课"); 发布订阅者模式 发布订阅者模式 // 创建一个对象 // 在该对象上创建一个缓存列表( 调度中心) // on 方法用来把函数 fn 都加到缓存列表中( 订阅者注册事件到调度中心) // emit 方法取到 arguments 里第一个当做 event, 根据 event 值去执行对应缓存列表中的函数( 发布者发布事件到调度中心, 调度中心处理代码) // off 方法可以根据 event 值取消订阅( 取消订阅) // once 方法只监听一次, 调用完毕后删除缓存函数( 订阅一次) // 公众号对象 // let eventEmitter = {}; // // 缓存列表,存放 event 及 fn // eventEmitter.list = {}; // // 订阅 // eventEmitter.on = function (event, fn) { // console.log(this,"this") // let _this = this; // // 如果对象中没有对应的 event 值,也就是说明没有订阅过,就给 event 创建个缓存列表 // // 如有对象中有相应的 event 值,把 fn 添加到对应 event 的缓存列表里 // (_this.list[event] || (_this.list[event] = [])).push(fn); // return _this; // }; // // 发布 // eventEmitter.emit = function () { // console.log(this,"this") // let _this = this; // // 第一个参数是对应的 event 值,直接用数组的 shift 方法取出 // console.log(arguments,"arguments") // let event = [].shift.call(arguments), // fns = [..._this.list[event]]; // // 如果缓存列表里没有 fn 就返回 false // if (!fns || fns.length === 0) { // return false; // } // // 遍历 event 值对应的缓存列表,依次执行 fn // fns.forEach(fn => { // fn.apply(_this, arguments); // }); // return _this; // }; // function user1(content) { // console.log('用户1订阅了:', content); // }; // function user2(content) { // console.log('用户2订阅了:', content); // }; // // 订阅 // eventEmitter.on('article', user1); // eventEmitter.on('article', user2); // // 发布 // eventEmitter.emit('article', 'Javascript 发布-订阅模式'); // /* // 用户1订阅了: Javascript 发布-订阅模式 // 用户2订阅了: Javascript 发布-订阅模式 // */ let eventEmitter = { // 缓存列表 list: {}, // 订阅 on(event, fn) { let _this = this; // 如果对象中没有对应的 event 值,也就是说明没有订阅过,就给 event 创建个缓存列表 // 如有对象中有相应的 event 值,把 fn 添加到对应 event 的缓存列表里 (_this.list[event] || (_this.list[event] = [])).push(fn); return _this; }, // 监听一次 once(event, fn) { // 先绑定,调用后删除 let _this = this; function on() { _this.off(event, on); fn.apply(_this, arguments); } on.fn = fn; _this.on(event, on); return _this; }, // 取消订阅 off(event, fn) { let _this = this; let fns = _this.list[event]; // 如果缓存列表中没有相应的 fn,返回false if (!fns) return false; if (!fn) { // 如果没有传 fn 的话,就会将 event 值对应缓存列表中的 fn 都清空 fns && (fns.length = 0); } else { // 若有 fn,遍历缓存列表,看看传入的 fn 与哪个函数相同,如果相同就直接从缓存列表中删掉即可 let cb; for (let i = 0, cbLen = fns.length; i < cbLen; i++) { cb = fns[i]; if (cb === fn || cb.fn === fn) { fns.splice(i, 1); break } } } return _this; }, // 发布 emit() { let _this = this; // 第一个参数是对应的 event 值,直接用数组的 shift 方法取出 let event = [].shift.call(arguments), fns = [..._this.list[event]]; // 如果缓存列表里没有 fn 就返回 false if (!fns || fns.length === 0) { return false; } // 遍历 event 值对应的缓存列表,依次执行 fn fns.forEach(fn => { fn.apply(_this, arguments); }); return _this; } }; function user1(content) { console.log('用户1订阅了:', content); } function user2(content) { console.log('用户2订阅了:', content); } function user3(content) { console.log('用户3订阅了:', content); } function user4(content) { console.log('用户4订阅了:', content); } // 订阅 eventEmitter.on('article1', user1); eventEmitter.on('article1', user2); eventEmitter.on('article1', user3); // 取消user2方法的订阅 eventEmitter.off('article1', user2); eventEmitter.once('article2', user4) // 发布 eventEmitter.emit('article1', 'Javascript 发布-订阅模式'); eventEmitter.emit('article1', 'Javascript 发布-订阅模式'); eventEmitter.emit('article2', 'Javascript 观察者模式'); eventEmitter.emit('article2', 'Javascript 观察者模式'); // eventEmitter.on('article1', user3).emit('article1', 'test111'); /* 用户1订阅了: Javascript 发布-订阅模式 用户3订阅了: Javascript 发布-订阅模式 用户1订阅了: Javascript 发布-订阅模式 用户3订阅了: Javascript 发布-订阅模式 用户4订阅了: Javascript 观察者模式 */ 命令模式 命令模式的第二种应用 刷新菜单目录 增加子菜单 删除子菜单 更新子菜单 // 如下代码上的四个按钮 点击事件 var b1 = document.getElementById("button1"), b2 = document.getElementById("button2"), b3 = document.getElementById("button3"), b4 = document.getElementById("button4"); /* bindEnv函数负责往按钮上面安装点击命令。点击按钮后,会调用 函数 */ var bindEnv = function (button, func) { button.onclick = function () { func(); } }; // 现在我们来编写具体处理业务逻辑代码 var Todo1 = { test1: function () { alert("我是来做第一个测试的"); } }; // 实现业务中的增删改操作 var Menu = { add: function () { alert("我是来处理一些增加操作的"); }, del: function () { alert("我是来处理一些删除操作的"); }, update: function () { alert("我是来处理一些更新操作的"); } }; // 调用函数 bindEnv(b1, Todo1.test1); // 增加按钮 bindEnv(b2, Menu.add); // 删除按钮 bindEnv(b3, Menu.del); // 更改按钮 bindEnv(b4, Menu.update); 命令模式的例子 命令模式 刷新菜单目录 增加子菜单 删除子菜单 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); 总结

我是歌谣 最好的种树是十年前 其次是现在 加油 歌谣

收藏 评论 分享 举报

上一篇:#yyds干货盘点 前端小知识点扫盲笔记记录6

下一篇:ant design table实现上下行拖拽功能(类组件)



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有