JavaScript忍者秘籍 控制对象访问、集合

2023-10-29 21:10

本文主要是介绍JavaScript忍者秘籍 控制对象访问、集合,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

对象中的getter、setter

const ninjaCollection = {ninjas: ["Yoshi", "Kuma", "Hattori"],get firstNinja() {report("Getting firstNinja");return this.ninjas[0];},set firstNinja(value) {report("Setting firstNinja");this.ninjas[0] = value;}
};

getter、setter

class中的getter、setter

class NinjaCollection {constructor(){this.ninjas = ["Yoshi", "Kuma", "Hattori"];}get firstNinja(){report("Getting firstNinja");return this.ninjas[0];}set firstNinja(value){report("Setting firstNinja");this.ninjas[0] = value;}}

注意:class内getter和setter可以单独定义,但是在非严格模式下,仅定义getter,浏览器会忽略请求,导致getter不起作用,而在严格模式下,仅有getter会报异常Object.definedProperty中getter、setter
为什么使用Object.definedProperty?
传统意义上,getter、setter用于访问私有对象属性,而js没有私有对象,一般使用闭包模拟私有对象,使用getter、setter实现对私有对象属性的访问。

"use strict";
function Ninja() {let _skillLevel = 0;Object.defineProperty(this, 'skillLevel', { //使用Object.defineProperty定义属性skillLevelget: () => {report("The get method is called");return _skillLevel;},set: value => {report("The set method is called");_skillLevel = value;}});}
assert(ninja.skillLevel === 0, "The getter works fine!"); //隐式使用get方法
ninja.skillLevel = 10; //赋值 隐式调用set方法

代理 -ES6 
通过代理控制对另一个对象的访问,可以定义当对象发生交互时可执行的自定义行为(读取或设置属性值、调用方法等),可以将代理理解为通用化的getter、setter,区别是每个getter、setter仅能控制单个对象属性,而代理可以用于对象交互的通用处理,包括调用对象的方法。使用代理会带来性能问题。Proxy构造器创建代理

const emperor = { name: "Komei" };
const representative = new Proxy(emperor, { //通过Proxy构造器创建代理,传入对象emperor,以及包含get、set方法的对象,用于处理对象属性的读写操作get: (target, key) => {report("Reading " + key + " through a proxy");return key in target ? target[key]: "Don’t bother the emperor!"},set: (target, key, value) => {report("Writing " + key + " through a proxy");target[key] = value;}
});                            assert(emperor.name === "Komei", "The emperor’s name is Komei");
assert(representative.name === "Komei","We can get the name property through a proxy");assert(emperor.nickname === undefined,"The emperor doesn’t have a nickname ");
assert(representative.nickname === "Don’t bother the emperor!","The proxy jumps in when we make inproper requests");representative.nickname = "Tenno";
assert(emperor.nickname === "Tenno","The emperor now has a nickname");
assert(representative.nickname === "Tenno","The nickname is also accessible through the proxy");

直接访问与代理访问区别
 

直接访问与间接访问

使用proxy记录日志,很有意思

function makeLoggable(target){return new Proxy(target, { //针对target创建代理get: (target, property) => {report("Reading " + property); //get方法时记录日志return target[property];},set: (target, property, value) => {report("Writing value " + value + " to " + property); //set方法时记录日志target[property] = value;}});}let ninja = { name: "Yoshi"};ninja = makeLoggable(ninja);assert(ninja.name == "Yoshi", "Our ninja Yoshi");ninja.weapon = "sword"; //对代理读写操作时都会记录日志


处理集合
使用对象作为字典或Map的常见缺陷有哪些?
在Map中,键值对可以是哪些类型?
Set中的成员必须是相同类型吗?


创建数组的两种基本方式
1. 使用内置的Array结构
2. 使用数组字面量[]

const arr1 = new Array("val1","val2");
const arr2 = ["val1","val2"];  //更优

为什么用数组字面量创建数组更优?
1. 占字符数量更少 
[] -2个字符 new Array() -11个字符
2. js具有高度动态特性,组发阻止修改内置Array构造函数,也就意味着new Array()创建的不一定是数组

数组元素操作
push:在数组末尾添加元素
unshift:在数组开头添加元素
pop:在数组尾部删除元素
shift:在数组开头删除元素
pop、push操作比shift、unshift操作快很多,因为后者在头部删除或添加元素后需要调整后面元素的位置

delete:直接删除元素
delete方法删除元素并非真正的删除了元素,而是将原来的元素置空,数组的长度在delete前后不会发生变化。
delete arr1[0]; 
splice:在任意位置删除或插入元素,数组长度会更改
arr.splice(1,2); //从下标1开始删除两个元素,若第二个元素为空,则删除到数组末尾,返回删除的数组元素
arr.splice(1,2,'addVal1',"addVal2"); //从下标1开始移除两个元素,并添加两个元素addVal1,addVal2

数组操作
1. 遍历:for、foreach

ninjas.forEach(ninja => {assert(ninja !== null, ninja);
});

使用foreach,遍历每个数组元素会立即执行,不需要考虑起始索引、结束条件和计步器

2. 映射数组:foreach、map
映射数组即将数组中的每个元素的属性映射到新数组的元素上

const ninjas = [{name: "Yagyu", weapon: "shuriken"},{name: "Yoshi", weapon: "katana"},{name: "Kuma", weapon: "wakizashi"}
];
//foreach 映射数组
const weapons = [];
ninjas.forEach(ninja => {weapons.push(ninja.weapon);
}); 
//map映射
const weapons = ninjas.map(ninja => ninja.weapon);

map创建一个全新数组,遍历输入,对数组中的每个元素在新建的数组上都会基于回调函数的执行结果创建一个对应元素。

3. 测试数组元素:every、some

const allNinjasAreNamed = ninjas.every(ninja => "name" in ninja); //当每个ninja对象都含有name属性才会返回true
const allNinjasAreArmed = ninjas.some(ninja => "weapon" in ninja); //部分元素满足条件返回true

4. 查找元素 find、filter、indexOf、lastIndexOf、findIndex

const ninjaWithWakizashi = ninjas.find(ninja => ninja.weapon === "wakizashi");

find返回满足查询条件的第一个元素,若未查询到满足条件的元素,返回undefined

const ninjaWithWakizashi = ninjas.filter(ninja => "weapon" in ninja);

filter返回满足查询条件的多个元素
indexOf:查询元素的第一个索引
lastIndexOf:查询元素的最后一个索引

const yoshiIndex = ninjas.findIndex(ninja => ninja === "Yoshi");

findIndex:查询元素的第一个索引

5. 数组排序 sort 
sort需要提供回调函数,并按回调函数的返回值进行排序
· 若回调函数的返回值 < 0 ,元素a排在元素b前面
· 若回调函数的返回值 > 0 ,元素a排在元素b后面
· 若回调函数的返回值 = 0 ,元素a与元素b出现在相同位置

const ninjas = [{name: "Yoshi"}, {name: "Yagyu"}, {name: "Kuma"}];
ninjas.sort(function(ninja1, ninja2){if(ninja1.name < ninja2.name) { return -1; }if(ninja1.name > ninja2.name) { return 1; }return 0;
}); 

6. 合计数组元素 foreach、reduce

arr.reduce(func(),initialVal); //func() 回调函数, initialVal 传递给回调函数的初始值
const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((aggregated, number) => aggregated + number, 0);

Map 
1. 创建Map

var ninjaMap = new Map();

2. Map元素操作
map.delete(key):从map中删除key 
map.clear():清空map
map.has(key): map中是否包含key
map.get(key):获取key对应的值,不存在返回undefined
map.size:map存储映射数量

2. key相等
对于java、c#来说,map中不能存储相同的两个key
而js中允许两个对象的内容相同,且不能为同一个对象!

const map = new Map();
const currentLocation = location.href;
const firstLink = new URL(currentLocation);
const secondLink = new URL(currentLocation);
map.set(firstLink, { description: "firstLink"});
map.set(secondLink, { description: "secondLink"});

3. 遍历map for...of
map总有两个值数组:key、value数组分别为map.keys(),map.values()

for(var item of map.keys/values()){}

Set 
集合中的每个元素都是唯一的。
1. 创建set

const ninjas = new Set(["value1","value2"]);

2. set元素操作
set.has(val):set是否包含val元素
set.size:set中元素数量
set.add(val):添加set元素
3.并集、交集、差集

const ninjas = ["Kuma", "Hattori", "Yagyu"];
const samurai = ["Hattori", "Oda", "Tomoe"];
//并集 -自动去重
const warriors = new Set([...ninjas, ...samurai]);
//交集 
const ninjaSamurais = new Set([...ninjas].filter(ninja => samurai.has(ninja)) ); 
//使用延展运算符将集合转换为数组
//差集
const pureNinjas = new Set([...ninjas].filter(ninja => !samurai.has(ninja)));

 

这篇关于JavaScript忍者秘籍 控制对象访问、集合的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/303376

相关文章

JavaScript中的isTrusted属性及其应用场景详解

《JavaScript中的isTrusted属性及其应用场景详解》在现代Web开发中,JavaScript是构建交互式应用的核心语言,随着前端技术的不断发展,开发者需要处理越来越多的复杂场景,例如事件... 目录引言一、问题背景二、isTrusted 属性的来源与作用1. isTrusted 的定义2. 为

Java循环创建对象内存溢出的解决方法

《Java循环创建对象内存溢出的解决方法》在Java中,如果在循环中不当地创建大量对象而不及时释放内存,很容易导致内存溢出(OutOfMemoryError),所以本文给大家介绍了Java循环创建对象... 目录问题1. 解决方案2. 示例代码2.1 原始版本(可能导致内存溢出)2.2 修改后的版本问题在

Java CompletableFuture如何实现超时功能

《JavaCompletableFuture如何实现超时功能》:本文主要介绍实现超时功能的基本思路以及CompletableFuture(之后简称CF)是如何通过代码实现超时功能的,需要的... 目录基本思路CompletableFuture 的实现1. 基本实现流程2. 静态条件分析3. 内存泄露 bug

Java中Object类的常用方法小结

《Java中Object类的常用方法小结》JavaObject类是所有类的父类,位于java.lang包中,本文为大家整理了一些Object类的常用方法,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. public boolean equals(Object obj)2. public int ha

SpringBoot项目中Maven剔除无用Jar引用的最佳实践

《SpringBoot项目中Maven剔除无用Jar引用的最佳实践》在SpringBoot项目开发中,Maven是最常用的构建工具之一,通过Maven,我们可以轻松地管理项目所需的依赖,而,... 目录1、引言2、Maven 依赖管理的基础概念2.1 什么是 Maven 依赖2.2 Maven 的依赖传递机

SpringBoot实现动态插拔的AOP的完整案例

《SpringBoot实现动态插拔的AOP的完整案例》在现代软件开发中,面向切面编程(AOP)是一种非常重要的技术,能够有效实现日志记录、安全控制、性能监控等横切关注点的分离,在传统的AOP实现中,切... 目录引言一、AOP 概述1.1 什么是 AOP1.2 AOP 的典型应用场景1.3 为什么需要动态插

Java实现Excel与HTML互转

《Java实现Excel与HTML互转》Excel是一种电子表格格式,而HTM则是一种用于创建网页的标记语言,虽然两者在用途上存在差异,但有时我们需要将数据从一种格式转换为另一种格式,下面我们就来看看... Excel是一种电子表格格式,广泛用于数据处理和分析,而HTM则是一种用于创建网页的标记语言。虽然两

java图像识别工具类(ImageRecognitionUtils)使用实例详解

《java图像识别工具类(ImageRecognitionUtils)使用实例详解》:本文主要介绍如何在Java中使用OpenCV进行图像识别,包括图像加载、预处理、分类、人脸检测和特征提取等步骤... 目录前言1. 图像识别的背景与作用2. 设计目标3. 项目依赖4. 设计与实现 ImageRecogni

Java中Springboot集成Kafka实现消息发送和接收功能

《Java中Springboot集成Kafka实现消息发送和接收功能》Kafka是一个高吞吐量的分布式发布-订阅消息系统,主要用于处理大规模数据流,它由生产者、消费者、主题、分区和代理等组件构成,Ka... 目录一、Kafka 简介二、Kafka 功能三、POM依赖四、配置文件五、生产者六、消费者一、Kaf

Java访问修饰符public、private、protected及默认访问权限详解

《Java访问修饰符public、private、protected及默认访问权限详解》:本文主要介绍Java访问修饰符public、private、protected及默认访问权限的相关资料,每... 目录前言1. public 访问修饰符特点:示例:适用场景:2. private 访问修饰符特点:示例: