当前位置: 首页 > news >正文

web前端之JavaScript

MENU

  • JavaScript之设计模式、单例、代理、装饰者、中介者、观察者、发布订阅、策略
  • JavaScript之数组静态方法的实现、reduce、forEach、map、push、every


JavaScript之设计模式、单例、代理、装饰者、中介者、观察者、发布订阅、策略

单例模式
概念

保证一个类仅有一个实例,并提供一个访问它的全局访问点。实现的方法为先判断实例存在与否,如果存在则直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。


适用场景

一个单一对象。比如:弹窗,无论点击多少次,弹窗只应该被创建一次。


代码实现

class CreateUser {constructor(name) {this.name = name;this.getName();};getName() {console.log(this.name);};
};// 代理实现单例模式
let ProxyMode = (function () {let instance = null;return function (name) {if (!instance) instance = new CreateUser(name);return instance;};
})();// 测试单体模式的实例
let a = new ProxyMode("aaa");
console.log(a);
// CreateUser {name: "aaa"}let b = new ProxyMode("bbb");
console.log(b);
// CreateUser {name: "aaa"}// 因为单体模式是只实例化一次,
// 所以下面的实例是相等的
console.log(a === b);
// true

代理模式
概念

为一个对象提供一个代用品或占位符,以便控制对它的访问。


常用的虚拟代理形式

某一个花销很大的操作,可以通过虚拟代理的方式延迟到这种需要它的时候才去创建(例:使用虚拟代理实现图片懒加载)。


图片懒加载的方式

先通过一张loading图占位,然后通过异步的方式加载图片,等图片加载好了再把完成的图片加载到img标签里面。


解释

使用代理模式实现图片懒加载的优点还有符合单一职责原则。减少一个类或方法的粒度和耦合度。


代码实现

let imgFunc = (function() {// 创建一个img标签let imgNode = document.createElement('img');// 把标签放到body上document.body.appendChild(imgNode);// 返回setSrc函数return {setSrc: function(src) {imgNode.src = src;}};
})();let proxyImage = (function() {// 创建一个img标签let img = new Image();// 给img标签添加自执行函数img.onload = function() {imgFunc.setSrc(this.src);};return {setSrc: function(src) {imgFunc.setSrc('/img/loading02.gif');setTimeout(() => {img.src = src;}, 1000);}};
})();console.log(proxyImage);
// {setSrc: ƒ}proxyImage.setSrc('/img/08.jpg');

装饰者模式
概念

在不改变对象自身的基础上,在程序运行期间给对象动态地添加方法。


例如

现有4种型号的自行车分别被定义成一个单独的类,如果给每辆自行车都加上前灯、尾灯、铃铛这3个配件,如果用类继承的方式,需要创建4 * 3 = 12个子类。但如果通过装饰者模式,只需要创建3个类。


适用的场景

原有方法维持不变,在原有方法上再挂载其他方法来满足现有需求;函数的解耦,将函数拆分成多个可复用的函数,再将拆分出来的函数挂载到某个函数上,实现相同的效果但增强了复用性。


用AOP装饰函数实现装饰者模式

Function.prototype.before = function(beforefn) {// 保存原函数引用let self = this;// 返回包含了原函数和新函数的'代理函数'return function() {// 执行新函数,修正thisbeforefn.apply(this, arguments);// 执行原函数return self.apply(this, arguments);};
};Function.prototype.after = function(afterfn) {let self = this;return function() {let ret = self.apply(this, arguments);afterfn.apply(this, arguments);return ret;};
};let func = function() {console.log('2');
};// func1和func3为挂载函数
let func1 = function() {console.log('1');
};let func3 = function() {console.log('3');
};func = func.before(func1).after(func3);
func();
// 1  2  3

中介者模式
概念

通过一个中介者对象,其他所有的相关对象都通过该中介者对象来通信,而不是相互引用,当其中的一个对象发生改变时,只需要通知中介者对象即可。通过中介者模式可以解除对象与对象之间的紧耦合关系。


例如

现实生活中,航线上的飞机只需要和机场的塔台通信就能确定航线和飞行状态,而不需要和所有飞机通信。同时塔台作为中介者,知道每架飞机的飞行状态,所以可以安排所有飞机的起降和航线安排。


适用的场景

例如购物车需求,存在商品选择表单、颜色选择表单、购买数量表单等,都会触发change事件,那么可以通过中介者来转发处理这些事件,实现各个事件间的解耦,仅仅维护中介者对象即可。


html

<div><div><span>选择颜色: </span><select id="colorSelect"><option value="">请选择</option><option value="red">红色</option><option value="blue">蓝色</option></select></div><div><span>选择内存: </span><select id="memorySelect"><option value="">请选择</option><option value="32G">32G</option><option value="16G">16G</option></select></div><div><span>输入购买数量: </span><input type="text" id="numberInput" /></div><div><span>您选择了颜色: </span><span id="colorInfo"></span></div><div><span>您选择了内存: </span><span id="memoryInfo"></span></div><div><span>您输入了数量: </span><span id="numberInfo"></span></div><div><button id="nextBtn" disabled="true">请选择手机颜色、内存和购买数量</button></div>
</div><script src="./index.js"></script>

JavaScript

// 手机库存数据
let goods = { "red|32G": 3, "red|16G": 0, "blue|32G": 1, "blue|16G": 6 };// 中介者对象
let mediator = (function () {let colorSelect = document.getElementById('colorSelect'),memorySelect = document.getElementById('memorySelect'),numberInput = document.getElementById('numberInput'),colorInfo = document.getElementById('colorInfo'),memoryInfo = document.getElementById('memoryInfo'),numberInfo = document.getElementById('numberInfo'),nextBtn = document.getElementById('nextBtn'),regNumber = /^[1-9]{1}[0-9]{0,2}$/;return {changed: function (obj) {// 颜色let color = colorSelect.value,// 内存memory = memorySelect.value,// 数量number = numberInput.value,// 颜色和内存对应的手机库存数量stock = goods[`${color}|${memory}`];// 如果改变的是选择颜色下拉框if (obj === colorSelect) {colorInfo.innerHTML = color;} else if (obj === memorySelect) {memoryInfo.innerHTML = memory;} else if (obj === numberInput) {numberInfo.innerHTML = number;}if (!color) return (nextBtn.disabled = true, nextBtn.innerHTML = '请选择手机颜色');if (!memory) return (nextBtn.disabled = true, nextBtn.innerHTML = '请选择内存大小');if (!regNumber.test(number)) return (nextBtn.disabled = true, nextBtn.innerHTML = '请输入正确的购买数量');if (number > stock) return (nextBtn.disabled = true, nextBtn.innerHTML = '库存不足');nextBtn.disabled = false;nextBtn.innerHTML = '放入购物车';}}
})();// 事件函数
// id选择器可以直接绑定事件,不需要特意获取。
colorSelect.onchange = function () {mediator.changed(this);
};
memorySelect.onchange = function () {mediator.changed(this);
};
numberInput.oninput = function () {mediator.changed(this);
};

相关链接

1、掘金-原文


html

<div><span>选择颜色:</span><select id="colorSelect"><option value="">请选择</option><option value="red">红色</option><option value="blue">蓝色</option></select>
</div>
<div><span>输入购买数量: </span><input type="text" id="numberInput" />
</div><div><span>您选择了颜色: </span><span id="colorInfo"></span>
</div>
<div><span>您输入了数量: </span><span id="numberInfo"></span>
</div>
<div><button id="nextBtn" disabled="true">请选择手机颜色和购买数量</button>
</div><script src="./index.js"></script>

JavaScript

var colorSelect = document.getElementById('colorSelect'),numberInput = document.getElementById('numberInput'),colorInfo = document.getElementById('colorInfo'),numberInfo = document.getElementById('numberInfo'),nextBtn = document.getElementById('nextBtn');// 手机库存数据
var goods = {"red": 3,"blue": 6
};colorSelect.onchange = function () {// 获取选中的颜色值var color = this.value,// 数量number = numberInput.value,// 该颜色手机对应的当前库存stock = goods[color];console.log(color, number);// 赋值colorInfo.innerHTML = color;if (!color) {nextBtn.disabled = true;nextBtn.innerHTML = '请选择手机颜色';return;}// 用户输入的购买数量是否为正整数if (((number - 0) | 0) !== number - 0) {nextBtn.disabled = true;nextBtn.innerHTML = '请输入正确的购买数量';return;}// 当前选择数量超过库存量if (number > stock) {nextBtn.disabled = true;nextBtn.innerHTML = '库存不足';return;}nextBtn.disabled = false;nextBtn.innerHTML = '放入购物车';
};numberInput.oninput = function () {// 颜色var color = colorSelect.value,// 数量number = this.value,// 该颜色手机对应的当前库存stock = goods[color];numberInfo.innerHTML = number;if (!color) {nextBtn.disabled = true;nextBtn.innerHTML = '请选择手机颜色';return;}// 输入购买数量是否为正整数if (((number - 0) | 0) !== number - 0) {nextBtn.disabled = true;nextBtn.innerHTML = '请输入正确的购买数量';return;}// 当前选择数量没有超过库存量if (number > stock) {nextBtn.disabled = true;nextBtn.innerHTML = '库存不足';return;}nextBtn.disabled = false;nextBtn.innerHTML = '放入购物车';
};

观察者模式

// 有一家猎人工会,
// 其中每个猎人都具有发布任务(publish),
// 订阅任务(subscribe)的功能
// 他们都有一个订阅列表来记录谁订阅了自己
// 定义一个猎人类
// 包括姓名,级别,订阅列表function Hunter(name, level) {this.name = name;this.level = level;this.list = [];
};// 在Hunter原型上添加publish方法
Hunter.prototype.publish = function(money) {console.log(this.level + '猎人' + this.name + '寻求帮助');this.list.forEach(function(item, index) {item(money);});
};// 在Hunter原型上添加subscribe方法
Hunter.prototype.subscribe = function(targrt, fn) {console.log(this.level + '猎人' + this.name + '订阅了' + targrt.name);targrt.list.push(fn);
};// 猎人工会走来了几个猎人
let hunterMing = new Hunter('小明', '黄金');
let hunterJin = new Hunter('小金', '白银');
let hunterZhang = new Hunter('小张', '黄金');
let hunterPeter = new Hunter(' Peter ', '青铜');// Peter等级较低,
// 可能需要帮助,
// 所以小明,小金,小张都订阅了Peter
hunterMing.subscribe(hunterPeter, function(money) {console.log('小明表示:' + (money > 200 ? '' : '暂时很忙,不能给予帮助'));
});hunterJin.subscribe(hunterPeter, function() {console.log('小金表示:给予帮助');
});hunterZhang.subscribe(hunterPeter, function() {console.log('小金表示:给予帮助');
});// Peter遇到困难,赏金198寻求帮助
hunterPeter.publish(198);

发布订阅模式
版本一

// 定义一家猎人工会
// 主要功能包括任务发布大厅(topics),
// 以及订阅任务(subscribe),
// 发布任务(publish)
let HunterUnion = {// 任务发布大厅topics: Object.create(null),// 发布任务(publish)publish: function (topic, money) {if (!this.topics[topic]) return false;for (let fn of this.topics[topic]) fn(money);},// 订阅任务(subscribe)subscribe: function (topic, fn) {if (!this.topics[topic]) this.topics[topic] = [];this.topics[topic].push(fn);},
};// 定义一个猎人类
// 包括姓名,级别
function Hunter(name, level) {this.name = name;this.level = level;
}// 订阅
Hunter.prototype.subscribe = function (topic, fn) {console.log(this.level + "猎人" + this.name + "订阅了狩猎" + topic + "的任务。");HunterUnion.subscribe(topic, fn);
};// 发布
Hunter.prototype.publish = function (topic, money) {console.log(this.level + "猎人" + this.name + "发布了狩猎" + topic + "的任务。");HunterUnion.publish(topic, money);
};// 猎人工会走来了几个猎人
let hunterMing = new Hunter("小明", "黄金");
let hunterJin = new Hunter("小金", "白银");
let hunterZhang = new Hunter("小张", "黄金");
let hunterPeter = new Hunter("Peter", "青铜");// Peter发布了狩猎tiger的任务
hunterPeter.publish("tiger", 198);// 小明,小金,小张分别订阅了狩猎tiger的任务
hunterMing.subscribe("tiger", function (money) {console.log("小明表示:" + (money > 200 ? "" : "不") + "接取任务。", money);
});hunterJin.subscribe("tiger", function (money) {console.log("小金表示:接取任务。", money);
});hunterZhang.subscribe("tiger", function (money) {console.log("小张表示:接取任务。", money);
});// 猎人们发布 (发布者) 或订阅 (观察者/订阅者)
// 任务都是通过猎人工会 (调度中心) 关联起来的,
// 他们没有直接的交流。

版本二

class PublishAndSubscribe {constructor() {// 收集订阅信息,调度中心this.eventList = {};}// 收集打包传入的数据// attributeName属性名// datas数据// fn 事件collects(attributeName, datas, fn) {if (!(this.eventList[attributeName] instanceof Array)) this.eventList[attributeName] = [];this.eventList[attributeName].push({ datas, fn });}// 通过属性名触发对应的事件// attributeName属性名release(attributeName) {if (!this.eventList[attributeName].length) throw "出错啦!";this.eventList[attributeName].forEach((item) => item.fn(item.datas));}// 通过属性名找到对应的属性下的数组// 通过id移出对应的数组项off(attributeName, id) {this.eventList[attributeName].forEach((item, index) => {if (item.datas.id == id) this.eventList[attributeName].splice(index, 1);});}
}let publishAndSubscribe = new PublishAndSubscribe();// 收集属性
// attributeName1,attributeName2,attributeName3
// 并且,给它们绑定值和事件
publishAndSubscribe.collects("attributeName1",{ id: 1, content: "A4" },function (datas) {console.log("接收发布的数据:", datas);}
);
publishAndSubscribe.collects("attributeName2",{ id: 2, content: { a: 1, b: 6, c: 4 } },function (datas) {console.log("接收发布的数据:", datas);}
);
publishAndSubscribe.collects("attributeName3",{id: 3,content: [1, 9, 6, 3],},function (datas) {console.log("接收发布的数据:", datas);}
);
publishAndSubscribe.collects("attributeName4",{id: 4,content: "array",},function (datas) {console.log("接收发布的数据:", datas);}
);// 通过属性触发对应的事件
publishAndSubscribe.release("attributeName1");
publishAndSubscribe.release("attributeName2");
publishAndSubscribe.release("attributeName3");
console.log("publishAndSubscribe:", publishAndSubscribe.eventList);// 移除
publishAndSubscribe.off("attributeName4", 4);
console.log("publishAndSubscribe:", publishAndSubscribe.eventList);
// publishAndSubscribe.release("attributeName4");
// Error: Failed to resolve async component default: 出错啦!

版本三

let publishAndSubscribe = {eventList: {},// 订阅add(propertyName, datas, listener) {if (!this.eventList[propertyName]) this.eventList[propertyName] = [];this.eventList[propertyName].push({ datas, listener });},// 发布triggle(propertyName) {this.eventList[propertyName] &&this.eventList[propertyName].forEach((item) => item.listener(item.datas));},// 移除removes(propertyName, fn) {if (!this.eventList[propertyName]) return false;let index = this.eventList[propertyName].findIndex((listener) => listener === fn);this.eventList[propertyName].splice(index, 1);},
};let event1 = (data) => {console.log("数据:", data);
};
let event2 = (data) => {console.log("数据:", data);
};
let event3 = (data) => {console.log("数据:", data);
};let datas = [1, 2, 3, 4, 5];// 订阅
publishAndSubscribe.add("property1", datas, event1);
publishAndSubscribe.add("property2", [9, 8, 6, 7, 3], event2);
publishAndSubscribe.add("property3", [], event3);// 移除
publishAndSubscribe.removes("property2", event2);// 发布
publishAndSubscribe.triggle("property1");
publishAndSubscribe.triggle("property2");
publishAndSubscribe.triggle("property3");

策略模式
概念

定义一系列的算法,把他们一个个封装起来,并且使他们可以相互替换。


目的

策略模式的目的就是将算法的使用和算法的实现分离开。


解释

一个基于策略模式的程序至少由两部分组成。第一个部分是一组策略类(可变),策略类封装了具体的算法,并负责具体的计算过程。第二个部分是环境类Context(不变),Context接受客户的请求,随后将请求委托给某一个策略类。要做到这一点,说明Context中要维持对某个策略对象的引用。


代码实现

// 策略类
let levelOBJ = {funA: function(money) {return money * 5;},funB: function(money) {return money * 3;},funC: function(money) {return money * 2;}
};// 环境类
let calculateBouns = function(level, money) {return levelOBJ[level](money);
};console.log(calculateBouns('funA', 10));
// 50
console.log(calculateBouns('funB', 20));
// 60
console.log(calculateBouns('funC', 30));
// 60

JavaScript之数组静态方法的实现、reduce、forEach、map、push、every

Array.prototype.myjoin
概念

join()方法将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串。如果数组只有一个项目,那么将返回该项目而不使用分隔符。


MDN链接地址

MDN - join


示例代码

let arrayData = [1, null, [2], 'string', [], { sname: 3 }, null, {}];Array.prototype.myjoin = function(separator) {// 如果 separator 是字符串类型,// 赋值为 separator ;// 否则,赋值为 , 。separator = typeof separator === 'string' ? separator : ',';// 获取 this 的长度。let len = this.length;// 初始化一个字符串let str = '';// 如果 len 等于 0 ,// 返回空字符串if (!len) return str;// 初始化 while 循环条件let i = 1;// 如果 this 的长度等于 1 ,// 直接返回且不加 , 。str = this[0] ? this[0].toString() : '';while (i < len) {str += separator + (this[i] ? this[i].toString() : '');i++;};return str;
};console.log(arrayData.myjoin());
// 1,,2,string,,[object Object],,[object Object]console.log(arrayData.myjoin(','));
// 1,,2,string,,[object Object],,[object Object]console.log(arrayData.myjoin('_'));
// 1__2_string__[object Object]__[object Object]console.log(arrayData.myjoin(':'));
// 1::2:string::[object Object]::[object Object]

Array.prototype.myfindIndex
概念

findIndex()方法返回数组中满足提供的测试函数的第一个元素的索引(下标)。若没有找到对应元素则返回-1。


MDN链接地址

MDN - findIndex


示例代码

let arrayData = [4, 6, 8, 12];Array.prototype.myfindIndex = function(callback, context) {// 获取第二个参数,// 即this指向。// 如果有直接使用,// 否则,指向windowcontext = context || window;// 获取this的长度。let len = this.length;// 初始化while的值。let i = 0;while (i < len) {// 调用函数if (callback.call(context, this[i], i, this)) return i;i++;};return -1;
};let fun = function(item) { return item + this.svalue > 10;
};console.log(arrayData.myfindIndex(fun, { svalue: 5 }));
// 1

Array.prototype.myreduce
概念

reduce()方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。


MDN链接地址

MDN - reduce


功能函数

Array.prototype.myreduce = function(callback, initialValue) {const len = this.length;let k = 0;// 如果this的长度等于0,// 抛出错误if (len == 0) {throw new TypeError('this is null or not defined');};// 如果callback的类型不是function函数类型,// 抛出错误if (typeof callback !== 'function') {throw new TypeError(callback + ' is not a function');};// 如果initialValue的值为undefined// 拿出this里面的第一个值作为累加值// 同时把k++ ,// 因为this[k]需要返回两个值// 第一个值是initialValue// 第二个值是this[k]// 如果initialValue的值不为undefined// 直接返回initialValue和this[k]// 此时this[k] => k = 0;if (initialValue === undefined) {initialValue = this[k++];};// 如果initialValue的值不是数字或者字符串类型的数字,// 抛出错误if (!/^(-?\d+)(\.\d+)?$/.test(initialValue)) {throw new TypeError(initialValue + ' is not number');};while (k < len) {// 如果this中的值不是数字或者字符串类型的数字,// 抛出错误if (!/^(-?\d+)(\.\d+)?$/.test(this[k])) {throw new TypeError(this[k] + ' is not number');};// 如果k的值在this中有对应的下标,// 就继续执行,// 否则退出if (k in this) {// Number(initialValue)把字符串类型的数字转为纯数字// Number(this[k])把字符串类型的数字转为纯数字// 回调函数的作用是将循环出来的数据返回到外面initialValue = callback.call(undefined, Number(initialValue), Number(this[k]), k, this);};k++;};return initialValue;
};

函数调用

// 纯数组求和
let sumNumF = function(item, num) {return item + num;
},dataNum = ['2', 3.1, '2.2'];console.log(dataNum.myreduce(sumNumF, '3.1'));
// 10.399999999999999// 数组对象求和
function sumObjF(item, num) {// Math.round(num)四舍五入return item + Math.round(num);
};let sumObj = [{id: 1,value: 2
}, {id: 2,value: 1
}, {id: 3,value: '1.4'
}, {id: 4,value: '2.6'
}];console.log(sumObj.map((item) => {return item.value;
}).myreduce(sumObjF)); // 7

Array.prototype.myforEach
概念

forEach()方法对数组的每个元素执行一次给定的函数。


MDN链接地址

MDN - forEach


功能函数

Array.prototype.myforEach = function() {const len = this.length;// 获取传入的第一参数// 回调函数let callback = arguments[0] || this;// 获取传入的第二个参数// 需要指向的this值let thisArg = arguments[1] || this;// 如果this的长度为0,抛出错误if (len == 0) {throw new TypeError('this is null or not defined');};// 如果传入的callback不是函数,抛出错误if (typeof callback !== "function") {throw new TypeError(callback + 'is not a function');};let k = 0;while (k < len) {// if in this对象中是否含有k属性// if('age' in data) data对象中是否含有age属性if (k in this) {// this[k] --- item// k --- i// this --- data// 循环调用传进来的函数// call改变this的指向// 回调函数的作用是将循环出来的值返回到外面callback.call(thisArg, this[k], k, this);};k++;};
};

函数调用

[10, 50, 90].myforEach((item, i, data) => {console.log(item);console.log(i);console.log(data);// 注意:使用箭头函数时,// this.a的值为undefinedconsole.log(this.a); }, {a: 1
});[10, 50, 90].myforEach(function(item, i, data) {console.log(item);console.log(i);console.log(data);// 注意 : 不使用箭头函数时,// this.a的值为传入的值console.log(this.a);}, {a: 1
});

Array.prototype.mymap
概念

map()方法创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值。


MDN链接地址

MDN - map


功能函数

Array.prototype.mymap = function(callback, thisPointTo) {const len = this.length;if (len == 0) {throw new TypeError('this is null or not defined');};if (typeof callback !== 'function') {throw new TypeError(callback + ' is not a function');};// 定义返回数组let result = [],i = 0;// 使用for循环遍历数据for (; i < len; i++) {if (i in this) {// 调用回调函数并传入新数组result[i] = callback.call(thisPointTo, this[i], i, this);};};// 返回新数组return result;
};

函数调用

let returnMap = [10, 50, 90].mymap((item, i, data) => {console.log(item);console.log(i);// 原始值不变console.log(data); // [10, 50, 90]// 注意 : 使用箭头函数时,// this.a 的值为 undefinedconsole.log(this.thisPointTo);item = 100;return item;
}, {thisPointTo: 1
});
console.log('returnMap:', returnMap); // returnMap: (3) [100, 100, 100]let returnMap = [10, 50, 90].mymap(function(item, i, data) {console.log(item);console.log(i);// 原始值不变console.log(data); // [10, 50, 90]// 注意 : 不使用箭头函数时,// this.a的值为传入的值console.log(this.thisPointTo);// 返回值item = 100;return item;
}, {thisPointTo: 1
});
console.log('returnMap:', returnMap); // returnMap: (3) [100, 100, 100]

Array.prototype.mypush
概念

push()方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度。


MDN链接地址

MDN - push


功能函数

Array.prototype.mypush = function() {// 初始化被push的数组长度,// 如果长度不是0,// 给len赋值为this.length;// 否则,赋值为0let len = this.length ? this.length : (this.length = 0) && 0;// 作用:逐一获取传进来的值let i = 0;while (i < arguments.length) {// 通过长度赋值给this数组。// 也就是向数组末尾添加元素。// 自带返回值this[len] = arguments[i];++i;// 同时this数组的长度也要++;++len;}// 给this数组的length属性重新赋值this.length = len;// 返回长度return this.length;
};

函数执行

let arrayData = [3, 'string'];
console.log(arrayData);
// [3, "string"]arrayData.mypush(1, '字符串', { sname: 'object 对象' }, ['array 数组']);console.log(arrayData);
// [3, "string", 1, "字符串", {…}, Array(1)]

Array.prototype.myevery
概念

every()方法测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值。
注意:若收到一个空数组,此方法在一切情况下都会返回true。


MDN链接地址

MDN - every


功能函数

Array.prototype.myevery = function(callback) {// 初始值为truelet isEvery = true;// 获取this的长度let len = this.length;// 初始化index let i = 0;// 获取第二个参数,// this是防止报错。// 第二个参数是一个对象,// 作用:改变this指向。let context = arguments[1] || this;while (i < len) {if (!callback.call(context, this[i], i, this)) {isEvery = false;break;};i++;}return isEvery;
};

传入函数

let fun = function(item, i) {console.log(item > this.svaleu);// 输出3次truereturn item > this.svaleu;
};

执行

let arrayData = [2, 3, 5];
console.log(arrayData.myevery(fun, { svaleu: 1 }));
// true

相关文章:

web前端之JavaScript

MENU JavaScript之设计模式、单例、代理、装饰者、中介者、观察者、发布订阅、策略JavaScript之数组静态方法的实现、reduce、forEach、map、push、every JavaScript之设计模式、单例、代理、装饰者、中介者、观察者、发布订阅、策略 单例模式 概念 保证一个类仅有一个实例&am…...

C# 图标标注小工具-查看重复文件

目录 效果 项目 代码 下载 效果 项目 代码 using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Windows.Forms;namespace ImageDuplicate {public partial clas…...

浅谈冯诺依曼体系和操作系统

&#x1f30e;冯诺依曼体系结构 文章目录 冯诺依曼体系结构 认识冯诺依曼体系结构       硬件分类       各个硬件的简单认识         输入输出设备         中央处理器         存储器 关于内存 对冯诺依曼体系的理解 操作系统 操作系统…...

Good Bye 2023

Good Bye 2023 Good Bye 2023 A. 2023 题意&#xff1a;序列a中所有数的乘积应为2023&#xff0c;现在给出序列中的n个数&#xff0c;找到剩下的k个数并输出&#xff0c;报告不可能。 思路&#xff1a;把所有已知的数字乘起来&#xff0c;判断是否整除2023&#xff0c;不够…...

多开工具对手机应用响应速度的优化与改进

多开工具对手机应用响应速度的优化与改进 摘要&#xff1a; 如今&#xff0c;手机应用的多样化和个性化需求不断增长&#xff0c;用户对应用的响应速度要求也越来越高。为了满足用户的需求&#xff0c;开发者们使用了多种技术手段进行应用的优化和改进。其中&#xff0c;多开工…...

文件批量整理,文件归类整理,文件批量归类

我们每天都要面对无数的文件&#xff0c;从工作报告、个人照片到电影和音乐。如何有效地管理和归类这些文件&#xff0c;成为了我们日常生活和工作中所要处理的。今天&#xff0c;小编就给大家介绍一款简单易用的工具——文件批量改名高手&#xff0c;助你轻松实现文件批量归类…...

Python+Django+Mysql+SimpleUI搭建后端用户管理系统(非常详细,每一步都清晰,列举了里面所有使用的方法属性)

一、在Anaconda环境下创建虚拟环境 &#xff08;1&#xff09;打开Anaconda Prompt(install)&#xff0c;创建虚拟环境&#xff0c;如下图所示&#xff1a; 方法一&#xff1a;默认情况下虚拟环境创建在Anaconda安装目录下的envs文件夹中 conda create --name usermanage …...

【Qt-QWidget-QLabel-QFrame-QSlider-View-Bar】

Qt编程指南 ■ Label■ QLabel■ QMovie 显示动画■ Widget■ QWidget■ QTabWidget■ QTableWidget■ QListWidget■ QStackedWidget■ QCalendarWidget■ QFrame■ QFrame■ View■ QT...

11|代理(上):ReAct框架,推理与行动的协同

11&#xff5c;代理&#xff08;上&#xff09;&#xff1a;ReAct框架&#xff0c;推理与行动的协同 在之前介绍的思维链&#xff08;CoT&#xff09;中&#xff0c;我向你展示了 LLMs 执行推理轨迹的能力。在给出答案之前&#xff0c;大模型通过中间推理步骤&#xff08;尤其…...

毫秒格式化

## 计算当前毫秒数&#xff1a; const [start,setStart] useState(new Date().getTime())useEffect(()>{setInterval(()>{setCurrMill(new Date().getTime()-start)},1)},[]) ## 格式化毫秒 function formatMilliseconds(milliseconds) {const totalSeconds Math.flo…...

pytorch与cuda版本对应关系汇总

pytorch与cuda版本关系 cuda版本支持pytorch版本cuda10.21.5 ~ 1.12cuda11.01.7 ~ 1.7.1cuda11.11.8 ~ 1.10.1cuda11.31.8.1 ~ 1.12.1cuda11.61.12.0 ~ 1.13.1cuda11.71.13.0 ~ 2.0.1cuda11.82.0.0 ~ 2.1.1cuda12.12.1.0 ~ 2.1.1 cuda 与 cudnn关系 cuda版本支持cudnn版本cu…...

Linux系统下隧道代理HTTP

在Linux系统下配置隧道代理HTTP是一个涉及网络技术的话题&#xff0c;主要目的是在客户端和服务器之间建立一个安全的通信通道。下面将详细解释如何进行配置。 一、了解基本概念 在开始之前&#xff0c;需要了解几个关键概念&#xff1a;代理服务器、隧道代理和HTTP协议。代理…...

unity学习笔记----游戏练习03

一、修复植物种植的问题 1.当手上存在植物时&#xff0c;再次点击卡片上的植物就会在手上添加新的植物&#xff0c;需要修改成只有手上没有植物时才能再次获取到植物。需要修改AddPlant方法。 public bool AddPlant(PlantType plantType) { //防止手上出现多个植…...

VistualStudio查看类图UML

点击菜单栏中的工具–》获取工具和功能。 然后在资源管理器中对应的代码中鼠标右键选择查看类图 生成一个ClassDiagram.cd文件就是类图的文件了。 根据需要拖拽就可以生成类图了。...

elasticsearch系列九:异地容灾-CCR跨集群复制

概述 起初只在部分业务中采用es存储数据&#xff0c;在主中心搭建了个集群&#xff0c;随着es在我们系统中的地位越来越重要&#xff0c;数据也越来越多&#xff0c;针对它的安全性问题也越发重要&#xff0c;那如何对es做异地容灾呢&#xff1f; 今天咱们就一起看下官方提供的…...

基于Java网上点餐系统设计与实现

博主介绍&#xff1a; ✌至今服务客户已经1000、专注于Java技术领域、项目定制、技术答疑、开发工具、毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅 &#x1f447;&#x1f3fb; 不然下次找不到 Java项目精品实…...

公司电脑文件加密系统——防止内部核心文件数据 | 资料外泄,自动智能透明加密保护

一套从源头上保障企业电脑数据安全和电脑使用安全的加密软件。天锐绿盾加密软件包含了表格数据加密、图纸加密、文档文件加密、内网文件加密流转、密级管控、电脑离线管理、文件外发管理、灵活的审批流程、工作模式切换、服务器白名单等功能。天锐绿盾加密系统全面覆盖Mac、Win…...

计算机毕业设计------ssm茶叶溯源系统

项目介绍 茶叶溯源系统&#xff0c;分为前台与后台。普通用户可在前台通过18位的编码查询茶叶的出售历史。 后台分为两种角色&#xff0c;管理员与经销商&#xff1b; 管理员主要功能包括&#xff1a; 主界面&#xff1b; 管理员管理&#xff1a;管理员列表、添加管理员&am…...

【网络安全 | Misc】miss_01 太湖杯

解压时提示输入密码&#xff1a; 如果 frFlags 或 deFlags 不为0会导致zip的伪加密 将deFlags的值修改为0 将9改为0&#xff0c;另存为123.zip&#xff1a; 即可绕过加密&#xff1a; 得到一个zip一个docx&#xff0c;但zip需要密码&#xff1a; 因此看docx有无敏感信息&#x…...

【深度学习目标检测】十一、基于深度学习的电网绝缘子缺陷识别(python,目标检测,yolov8)

YOLOv8是一种物体检测算法&#xff0c;是YOLO系列算法的最新版本。 YOLO&#xff08;You Only Look Once&#xff09;是一种实时物体检测算法&#xff0c;其优势在于快速且准确的检测结果。YOLOv8在之前的版本基础上进行了一系列改进和优化&#xff0c;提高了检测速度和准确性。…...

《深入理解C++11:C++11新特性解析与应用》笔记六

第六章 提高性能及操作硬件的能力 6.1 常量表达式 6.1.1 运行时常量性与编译时常量性 大多数情况下&#xff0c;const描述的是运行时常量性&#xff0c;也即是运行时数据的不可更改性。但有时候我们需要的却是编译时的常量性&#xff0c;这是const关键字无法保证的。例如&am…...

C# 基于事件的观察者模式

观察者模式是一种软件设计模式&#xff0c;用于定义对象之间的一对多依赖关系&#xff0c;当一个对象的状态发生变化时&#xff0c;它的所有依赖者&#xff08;观察者&#xff09;都将得到通知并自动更新。这种模式通过解耦合主题和观察者来提高对象的灵活性。 定义 观察者模式…...

ARM CCA机密计算软件架构之软件堆栈概述

Arm CCA平台通过硬件添加和固件组件的混合方式实现,例如在处理元素(PEs)中的RME以及特定的固件组件,特别是监视器和领域管理监视器。本节介绍Arm CCA平台的软件堆栈。 软件堆栈概述 领域VM的执行旨在与Normal world(正常世界)隔离,领域VM由Normal world Host(正常世界…...

《Python机器学习原理与算法实现》学习笔记

以下为《Python机器学习原理与算法实现》&#xff08;杨维忠 张甜 著 2023年2月新书 清华大学出版社&#xff09;的学习笔记。 根据输入数据是否具有“响应变量”信息&#xff0c;机器学习被分为“监督式学习”和“非监督式学习”。 “监督式学习”即输入数据中即有X变量&…...

k8s集群通过helm部署skywalking

1、安装helm 下载脚本安装 ~# curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 ~# chmod 700 get_helm.sh ~# ./get_helm.sh或者下载包进行安装 ~# wget https://get.helm.sh/helm-canary-linux-amd64.tar.gz ~# mv helm …...

介绍一款PDF在线工具

PDF是我们日常工作中的一种常见格式&#xff0c;其处理也是我们工作的重要基础性环节&#xff0c;一款可靠的处理工具显得十分重要。 完全免费、易于使用、丰富的PDF处理工具&#xff0c;包括&#xff1a;合并、拆分、压缩、转换、旋转和解锁PDF文件&#xff0c;以及给PDF文件…...

docker学习——汇总版

历时一个月将docker系统的学习了一下&#xff0c;并且记录了详细的笔记和实践过程。 希望能对工作需要的小伙伴们有所帮助~ docker基础篇 docker学习&#xff08;一、docker与VM对比&#xff09; docker学习&#xff08;二、安装docker&#xff09; docker学习&#xff08;…...

百度沧海文件存储CFS推出新一代Namespace架构

随着移动互联网、物联网、AI 计算等技术和市场的迅速发展&#xff0c;数据规模指数级膨胀&#xff0c;对于分布式文件系统作为大规模数据场景的存储底座提出了更高的要求。已有分布式文件系统解决方案存在着短板&#xff0c;只能适应有限的场景&#xff1a; >> 新型分布式…...

16-网络安全框架及模型-BiBa完整性模型

目录 BiBa完整性模型 1 背景概述 2 模型原理 3 主要特性 4 优势和局限性 5 应用场景 BiBa完整性模型 1 背景概述 Biba完整性模型是用于保护数据完整性的模型&#xff0c;它的主要目标是确保数据的准确性和一致性&#xff0c;防止未授权的修改和破坏。在这个模型中&#…...

ssm基于冲突动态监测算法的健身房预约系统的设计与实现论文

摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装健身房预约系统软件来发挥其高效地信息处理的作用&#xff…...

基于 Element UI 适用于 Vue 2 版本的虚拟列表选择器组件el-select

背景&#xff1a;在某些使用情况下&#xff0c;单个选择器可能最终加载数万行数据。 将这么多的数据渲染至 DOM 中可能会给浏览器带来负担&#xff0c;从而造成性能问题。 ——vue3element-plus有现成的轮子。而vue2element-ui没有。 以下 文章大部分 摘自 源组件中的README.md…...

java常见面试题:请解释一下Java中的常用分布式框架,如Spring Boot、Dubbo等。

下面我将详细介绍Java中的两个常用分布式框架&#xff1a;Spring Boot和Dubbo。 1. Spring Boot Spring Boot是一个用于创建独立、可运行的、生产级别的Spring应用程序的框架。它简化了Spring应用程序的创建和部署&#xff0c;使得开发人员能够专注于编写业务逻辑&#xff0c…...

FreeRTOS列表与列表项相关知识总结以及列表项的插入与删除实战

1.列表与列表项概念及结构体介绍 1.1列表项简介 列表相当于链表&#xff0c;列表项相当于节点&#xff0c;FreeRTOS 中的列表是一个双向环形链表 1.2 列表、列表项、迷你列表项结构体 1&#xff09;列表结构体 typedef struct xLIST { listFIRST_LIST_INTEGRITY_CHECK_VAL…...

07|输出解析:用OutputParser生成鲜花推荐列表

07&#xff5c;输出解析&#xff1a;用OutputParser生成鲜花推荐列表 模型 I/O Pipeline 下面先来看看 LangChain 中的输出解析器究竟是什么&#xff0c;有哪些种类。 LangChain 中的输出解析器 语言模型输出的是文本&#xff0c;这是给人类阅读的。但很多时候&#xff0c;你…...

cfa一级考生复习经验分享系列(十二)

背景&#xff1a;就职于央企金融机构&#xff0c;本科金融背景&#xff0c;一直在传统金融行业工作。工作比较忙&#xff0c;用了45天准备考试&#xff0c;几乎每天在6小时以上。 写在前面的话 先讲一下&#xff0c;整体一级考下来&#xff0c;我觉得知识点多&#xff0c;偏基础…...

【损失函数】SmoothL1Loss 平滑L1损失函数

1、介绍 torch.nn.SmoothL1Loss 是 PyTorch 中的一个损失函数&#xff0c;通常用于回归问题。它是 L1 损失和 L2 损失的结合&#xff0c;旨在减少对异常值的敏感性。 loss_function nn.SmoothL1Loss(reductionmean, beta1.0) 2、参数 size_average (已弃用): 以前用于确定是…...

Go语言中的HTTP重定向

大家好&#xff0c;我是你们可爱的编程小助手&#xff0c;今天我们要一起探讨如何使用Go语言实现HTTP重定向&#xff0c;让我们开始吧&#xff01; 大家都知道&#xff0c;网站开发中有时候需要将用户的请求从一个URL导向到另一个URL。比如说&#xff0c;你可能想将旧的URL结构…...

ORACLE P6 v23.12 最新虚拟机(VM)全套系统环境分享

引言 根据上周的计划&#xff0c;我简单制作了两套基于ORACLE Primavera P6 最新发布的23.12版本预构建了虚拟机环境&#xff0c;里面包含了全套P6 最新版应用服务 此虚拟机仅用于演示、培训和测试目的。如您在生产环境中使用此虚拟机&#xff0c;请先与Oracle Primavera销售代…...

鸿蒙开发ArkTS基础学习-开发准备工具配置

文章目录 前言1. 准备工作2.开发文档3.鸿蒙开发路径一.详情介绍二.DevEco Studio安装详解-开发环境搭建2.1配置开发环境欢迎各位读者阅读本文,今天我们将介绍鸿蒙(HarmonyOS)应用开发的入门步骤,特别是在准备工作和开发环境搭建方面的重要信息。本文将对鸿蒙官方网站的关键…...

WEB 3D技术 three.js 雾 基础使用讲解

本文 我们说一下 雾 在three.js中有一个 Fog类 它可以创建线性雾的一个效果 她就是模仿现实世界中 雾的一个效果 你看到远处物体会组件模糊 直到完全被雾掩盖 在 three.js 中 有两种雾的形式 一种是线性的 一种是指数的 个人觉得 线性的会看着自然一些 他是 从相机位置开始 雾…...

Python中的网络编程

IP地址 IPv4IPv6查看本机的IP地址 win ipconfiglinux ifconfig ping命令 ping www.baidu.com 查看是否能连通指定的网站ping 192.168.1.222 查看是否能连通指定的IP Port端口 0-65535 TCP/IP协议 传输数据之前要建立连接&#xff0c;通过三次握手建立&#xff1a; 客户端 --&g…...

uni-app js语法

锋哥原创的uni-app视频教程&#xff1a; 2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中..._哔哩哔哩_bilibili2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中...共计23条视频&#xff0c;包括&#xff1a;第1讲 uni…...

【论文阅读笔记】Detecting Camouflaged Object in Frequency Domain

1.论文介绍 Detecting Camouflaged Object in Frequency Domain 基于频域的视频目标检测 2022年发表于CVPR [Paper] [Code] 2.摘要 隐藏目标检测&#xff08;COD&#xff09;旨在识别完美嵌入其环境中的目标&#xff0c;在医学&#xff0c;艺术和农业等领域有各种下游应用。…...

Mysql(5日志备份恢复)

一.日志管理 MySQL 的日志默认保存位置为 /usr/local/mysql/data 先看下mysql的日志文件有无&#xff1a; 修改配置文件添加&#xff1a;错误日志&#xff0c;用来记录当MySQL启动、停止或运行时发生的错误信息&#xff0c;默认已开启 修改配置文件添加&#xff1a;通用查…...

MR实战:实现数据去重

文章目录 一、实战概述二、提出任务三、完成任务&#xff08;一&#xff09;准备数据文件1、在虚拟机上创建文本文件2、上传文件到HDFS指定目录 &#xff08;二&#xff09;实现步骤1、Map阶段实现&#xff08;1&#xff09;创建Maven项目&#xff08;2&#xff09;添加相关依赖…...

JVM 常用知识和面试题

1. 什么是JVM内存结构&#xff1f; jvm将虚拟机分为5大区域&#xff0c;程序计数器、虚拟机栈、本地方法栈、java堆、方法区&#xff1b; 程序计数器&#xff1a;线程私有的&#xff0c;是一块很小的内存空间&#xff0c;作为当前线程的行号指示器&#xff0c;用于记录当前虚拟…...

【教3妹学编程-算法题】一年中的第几天

3妹&#xff1a;“太阳当空照&#xff0c;花儿对我笑&#xff0c;小鸟说早早早&#xff0c;你为什么背上炸药包” 2哥 :3妹&#xff0c;什么事呀这么开森。 3妹&#xff1a;2哥你看今天的天气多好啊&#xff0c;经过了一周多的寒潮&#xff0c;天气总算暖和些了。 2哥&#xff…...

ramdump 中的memory统计

0. 前言 ramdump是指某个时刻系统或者子系统发生crash等异常&#xff0c;系统将内存中的数据通过一定的方式保存下来&#xff0c;相当于一个系统内存快照&#xff0c;用以开发者离线分析系统异常问题。 ramdump 工具中有很多内存统计的脚本&#xff0c;本文逐一剖析内存相关的…...

Element-Ui树形数据懒加载,删除到最后一个空数组不刷新问题

使用elemenui树形删除数据的时候刷新页面&#xff0c;我在网上找了好多方法&#xff0c;要么没用&#xff0c;要么都是部分代码&#xff0c;自己又看不懂&#xff0c;不得不硬着头皮看源码&#xff0c;发现了有个方法可以刷新。 使用elemenui树形删除数据的时候刷新页面。源码里…...

基于NASM搭建一个能编译汇编语言的汇编软件工具环境(利用NotePad++)

文章目录 一、创建汇编语言源程序二、Notepad的下载、安装、使用三、下载和安装编译器NASM3.1 下载NASM编译器3.2 安装并配置环境变量 四、编译汇编语言源程序&#xff08;使用命令&#xff09;五、下载和使用配套源码及工具六、将编译功能集成到Notepad 一、创建汇编语言源程序…...