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

成都网站制作公司seo问答

成都网站制作公司,seo问答,市场营销一般在哪上班,pmp数组本质是对象,键就是索引,值就是元素。 push /unshift 在数组最后/最前添加 pop /shift 把数组最后/最前的元素删除,返回的是被删除的元素 splice(0,2,5)从第0给位置开始删除2个元素,并添加一个元素 数组自带的…

数组本质是对象,键就是索引,值就是元素。

push  /unshift       在数组最后/最前添加

pop  /shift       把数组最后/最前的元素删除,返回的是被删除的元素

splice(0,2,5)从第0给位置开始删除2个元素,并添加一个元素

数组自带的排序方法

let arr=[2,5,4,3,1]

arr.sort((y,x)=>x-y)x-y>0交换顺序,不>0就不会交换顺序

最后结果时[2,3,4,5,6]顺序

arr.sort(x,y)

    迭代方法 every some filter map foreach reduce 

    arr.every((item)=>item>12)//如果每一项都满足条件,结果才是truearr.some((item)=>item>12)//只要有其中一项满足条件,结果就是true

map映射,简单来说,就像是一个“翻译器”或者“转换器”。它的主要工作就是将一种东西(比如数字、文字、对象等)按照一定的规则转换成另一种东西。

举个例子,假设你有一个列表,里面装着一些数字:[1, 2, 3, 4, 5]。现在你想把每个数字都变成它的两倍。那么,你可以使用map映射来实现这个目标。map映射会遍历这个列表,把每个数字都拿去乘以2,然后返回一个新的列表:[2, 4, 6, 8, 10]。

再比如,你有一个装着名字的列表:[“张三”, “李四”, “王五”]。你想把每个名字都变成“你好,XXX”的格式。使用map映射,你可以很容易地得到一个新的列表:[“你好,张三”, “你好,李四”, “你好,王五”]。

所以,map映射就是一个非常方便的工具,可以帮助我们快速地对一组数据进行统一的转换或处理。

forEach

     arr.forEach((item,index)=>console.log(item,index))//返回数组里每个元素和索引值

reduce

第一个元素是上一次执行的返回值

    let res=arr.reduce((item1,item2)=item1+item2)//将每一个元素累加

迭代器对象

每一个数组都有一个迭代器

    let ite=arr[Symbol.iterator]()

如上拿到迭代器接口

只要符合迭代器对象就能使用for of、循环遍历对象

    for(let i of arr){console.log(i); }
  console.log(arr.entries())

结果是迭代器对象

就能拿到键值对

  for(let i of arr.entries()){console.log(i);}

拿到键

  for(let i of arr.keys()){console.log(i);}

拿到元素的值

 for(let i of arr.values()){console.log(i);}

Arry.from将一个类似于数组的对象转化为真的数组结构

  function test(){console.log(Array.from(arguments));}
test(1,2,3)  

虽然test函数没有形参,但是用arguments可以找到,但是arguments是一个对象用from可以转化成对象

搜索 indexof  lastIndexof find findIndex findLast findLastIndex includes

indexof 

如果包含就返回正确的索引值,如果不包含就返回-1

let arr=[12,22,23]
arr.indexOf(15)
//结果是-1

includes

包含就返回true,不包含返回false

arr.includes(15)

find能返回最先满足条件的元素

findLast从后面开始查找

findIndex返回索引值

findLastIndex找出数组里最后一个大于10的元素

let res2=arr.findLastIndex(item=>item>10)

栈结构的封装

定义一个类,初始化一个元素。

  class stack{constructor(){this.item=[]}}let stack =new stack()

现在可以直接跳过constructor

  class stack{items=[]}
  • pop() 方法

    • pop() 方法应该是从栈中移除并返回最后一个元素,而不是添加元素。因此,pop() 方法不需要参数,并且应该调用 this.items.pop() 来移除数组中的最后一个元素。
  • peek() 方法

    • peek() 方法用于查看栈顶元素,但不移除它。因此,peek() 方法也不需要参数,并且应该返回 this.items[this.items.length - 1],而不是调用 this.items.peek()。因为 this.items 是一个数组,而数组没有 peek() 方法。
    • push(data) 方法
    • 接受一个参数 data,并将其添加到栈顶。
    • 返回undefined
    •     class stack {items = []pop(){this.items.push()}push(){this.items.push(data)}peek(data){return this.items[this.items.length-1]}isEmpty(){// return this.items.length===0return this.items.at(-1)}size(){return this.items.length}clear(){return this.items=[]}Tostring(){return this.items.join(',')}}let stack =new stack()
      

      由于我们可以随便用比如this.item.splice(0,2,9)的方式破坏栈,可以加下划线

              _items = []
      

      表示栈的私有性,来保护栈里的元素

    • 直至发布es13后才支持自带的属性用在前面加井号的方式

    •         #items = []
      

      每次访问stack.#items.push()用stack里面的方法才能改变栈的元素。直接stack.item会报错.

    • 用栈方法应用——解决十进制转换

    • 每一次把一个十进制的整数除以2的余数用push方法把余数push到栈里越往后的余数月堆到栈顶,再用pop方法把每次余数取出来,也就是从最后的余数取出

        let stack =new stack()function Dec(Decnumber){let remStack=new stack()let number=Decnumberlet string=""while(number>0){remStack.push(number)number=Math.floor(number%2)}while(!(remStack.isEmpty())){string+=remStack.pop()}return string}Dec(50)
      

      限制进制数如:8

    • 进制数如果是16,但是没有定义用ABCDEF表示10-16就需数组或者字符串定义

    •   function ECD(edcnumber){let string=''let rank=new stack()let number=edcnumberwhile(number>0){rank.push(number%2)number=Math.floor(number / 2) }while(!(rank.isEmpty())){string+=rank.pop()}return string}
      EDC(500,16)//让500按照16进制转换
      

      队列

    • 先进先出:像日常做核酸,排在列队头的人做完出去,队尾可以随时加人

    • 队列和栈差不多,不同的在于

    • dequeue:返回队头被删除的元素,方法里面用shift来删除第一个元素

    • enqueue:表示队尾添加

    • front:返回队头

      class stack{#item=[]
      dequeue(){
      return this.#item.shift()}enqueue(data){this.#item.push(data)}front(){return this.#item.push.at(0)}isEmpty(){return this.#item.length===0}size(){return this.#item.length}clear(){
      this.#item=[]}Tostring(){return this.#item.join(" ")}}
      

      但是:用shift的缺点是删除第一个元素就使后面的元素都往后移动一个。若数据太多对渲染效果有害,而delet方法使删除的元素位置上是empty。

    • class Queue{#items={}#lowCout=0//记队头的索引值#count=0//为每次改变往后移记录索引值dequeue() {if(this.isEmpty()){return undefined}//防止出现size负数let res=this.#items[this.#lowCout]delete this.#items[this.#lowCout]this.#lowCout++return res}enqueue(data) {this.#items[this.#count]=datathis. #count++}front() {return this.#items[this.#lowCout]}isEmpty() {return this.size()===0}size() {return this.#count-this.#lowCout}clear() {this.#items={}this.#lowCout = 0this.#count = 0}Tostring() {}}
      

    • 最应该采用对象obj的方式,来模拟数组

      obj={0:1,1:2,3:3}
      

      那么数据结构就会改变,所以之前的队列就不能用了。

    • 队列应用-——击鼓传花

    • 首先由几个玩家,规定一轮击鼓数为7.转为编程思想就是由队头被删并加在队尾,队列轮回后到谁时第七个结束谁出局。首先定义几个玩家,和击鼓传花数

    • game(['kerwin','xiaoming','tiechui','gangaer','guludunzi'],7)
      

      封装game函数

    • 1,new一个队列

    • let queue=new Queue()
      

    • 2,邀请玩家入场!

    • for(let i=0;i<list.length;i++){queue.enqueue(list[i])
      }
      

    • 3,开始游戏!

    • while(queue.size>1){for(let i=0;i<num;i++){queue.enqueue( queue.dequeue())}
      

      4,获胜者出列颁奖!

    • return queue.dequeue()
      

      完整代码

    • function game(list,num){
      let queue=new Queue()
      for(let i=0;i<list.length;i++){queue.enqueue(list[i])
      }
      while(queue.size>1){for(let i=0;i<num;i++){queue.enqueue( queue.dequeue())}console.log(queue.dequeue(),"淘汰了");
      }
      return queue.dequeue()
      }
      game(['kerwin','xiaoming','tiechui','gangaer','guludunzi'],7)
      

      双端队列

    • 可以从队头出,也可以从队头进,可以从队尾出,也可以从队尾进。例如,日常排队从队头插队,也可以看队太长了从队尾直接离开

    • 把方法改为从头加addFront

    • 分为三个情况:

    • lowcount(开头索引值)=0;把数组中后面的元素向后移动一位,把第一个位置空出来。然后在第一个位置上添加数据data。

    •         else{//lowcount从0开始for(let i=this.#count;i>0;i--){this.#items[i]=this.#items[i-1]}this.#items[0]=data //0的位置被移出来,就可以添加数据this.#count++}
      

    • lowcount(开头索引值)>0;把lowcount减一,留出0的位置。添加data

    •         if(this.#lowCout>0){this.#lowCout--this.#items[this.#lowCout]=data
      

    • 数组为空就可以直接添加复用addback方法。

    •       //如果为空if(this.isEmpty()){this.addBack(data)}
      

      还有新颖的是在队尾删除

    • 因为count是从0开始计数,最后一个元素队尾元素的索引是 #count - 1,因为数组索引从0开始。因此,#count 本身并不直接指向队尾元素,而是指向队尾元素之后的下一个位置(即队列的长度)。

        removeBack(){if(this.isEmpty()){return}this.#count--let res=this.#items[this.#count]delete this.#items[this.#count]return res}
      

      其他和单队列差不多

    • class Queue{#items#count=0#lowcountremoveFont(){let res=this.#items[this.#lowcount]delete this.#items[this.#lowcount]return res}addBack(){this.#items.this.#count=[data]this.count++}addFront(){if(this.isEmpty()){this.#items.addBack()}else{if(this.#lowcount>0){this.#lowcount--this.#items[this.#lowcount]=[data]}else {for(let i=0;i<this.#count;i++)this.#items[i+1]=this.#items[i]for(let i=this.#count;i>0;i--)this.#items[i]=this.#items[i-1]}}}removeBack(){if(this.isEmpty()){return}this.#count--let res=this.#items[this.#count]delete this.#items[this.#count]return res}isEmpty(){return this.size()===0}size(){return this.#count-this.#lowcount}peekFront(){return this.#items[this.#lowcount]}peekBack(){if(this.isEmpty()){return }return this.#items[this.#count-1]}toString(){let str=""for(let i=0;i<this.#count;i++){str=`${this.#items[i]}`}return str}
      }
      let dequeue=new Queue()
      function test(str){
      const lowstr=str.toLocalLowerCase().split("").join
      let queue=new Queue()
      for(let i=0;i<lowstr.length;i++){queue.addBack(lowstr[i])
      }
      console.log(dequeue);}
      

      应用:回文检查如dad

    • :split方法会自动缩进空格

    • function test(str){
      const lowstr=str.toLocalLowerCase().split("").join
      let queue=new Queue()
      for(let i=0;i<lowstr.length;i++){queue.addBack(lowstr[i])
      }
      while(dequeue.size()>1){if(dequeue.removeBack!==dequeue.removeFont){
      isEqual=falsebreak;}
      }
      }
      test('DA     D')
      

      链表

    • 模拟栈和队列,也有自己独特的魅力

    • 在构造函数中设置nextnull可以确保每个新创建的节点都默认没有指向下一个节点,合链表节点的初始状态。this.element = element;这行代码的作用是将传递给构造函数的element参数的值赋给新创建的节点实例的element属性。

    •   class Node {constructor(element) {this.element = element; // 节点存储的数据this.next = null; // 指向下一个节点的链接}
      }
    • 在linkedList中再定义记录节点位置和头节点

    • 1,在constructor构造函数器中用定义并初始化两个变量,cout用来记录链表中的节点,应为要从链头到链尾一点点找,还要初始化一个链头head

    • 2,push从后面插入

    •       push(){const node = new Node(element)if(head==null){this.head=Node  }else{let current=this.headwhile(current.next!==null){current =current.next}current.next=node}this.count++}
      

    • 3,删除分为两种:删除特定位置,删除特点元素数据

    • 删除特定位置

    •    //指定位置删除removeAt(index){if(index>=0&&index<this.count){let current=this.headif(index===0){this.head=this.head}else{let previousfor(let i=0;i<index;i++){previous=currentcurrent=current.next}previous.next=current.next}this.current--return current.element}}
      

    • 参数检查

    • 为了保护head不被破坏复制给current找节点头
      • 首先检查传入的索引 index 是否有效,即是否在链表的范围内(0 到 this.count - 1)。
    • 删除头节点

      • 如果 index 为 0,表示要删除的是头节点。在这种情况下,只需要将头节点指向下一个节点即可。
    • 删除非头节点

      • 如果 index 大于 0,则需要遍历链表找到要删除的节点及其前一个节点。
      • 使用两个指针 previous 和 current,其中 current 初始指向头节点。
      • 遍历链表,直到 current 指向要删除的节点。
      • 然后,将 previous 的 next 指针指向 current 的 next,从而跳过 current 节点,实现删除。
    • 更新计数

      • 删除节点后,应该减少链表的节点计数 this.count。但在您提供的代码中,这一步被遗漏了。
      • 你可能有这样的疑惑
      • 为什么 current 是正确的节点

      • 初始化时,current 指向头节点,这是已知的。
      • 循环确保了 current 指针从头节点开始,逐个节点移动,直到到达指定的索引位置。
      • 循环结束后,current 指针所指向的节点就是我们要删除的节点,因为我们已经根据 index 的值移动了 current 指针相应的次数。
      • 因此,不需要将 current 复制为 index,因为 current 的位置是通过遍历链表来确定的,而不是通过直接设置索引值。循环的结构和 current 指针的移动确保了在循环结束时,current 指向的是正确的节点。

      • 实验效果,为简化方法,封装一个函数来接节点

      •    getNodeAt(index){if(index>=0&&index.this.count){let node=this.headfor(let i=0;i<index;i++){node=node.next}return node}}
        

        在removeAt函数中precious调用函数接收节点

      •    removeAt(index){if(index>=0&&index<this.count){let current = this.headif(index===0){this.head=this.head}else{let previous=this.getNodeAt(index-1)previous.next=currentprevious.next=current.next}this.current--return current.element}}
        

        上面是根据节点位置删除,如果你想删除一个数据就需要下面的方法

      • 规定两个方法,第一个用于比对节点中你想找到的数值,并返回索引值

      • indexOf(element){let current =this.headfor(let i=0;i<this.count;i++){if(方法判断(element,current.element)){return i}current=current.next}
        return -1
        }
        

        在这个indexOf函数中,如果方法判断(element, current.element)返回true,那么return i;会被执行,函数会返回索引i,并且不会再执行current = current.next;或者任何后续的循环迭代。整个函数调用会结束,控制权会返回到调用indexOf函数的地方。

      • 第二个用于接收索引值,调上一个删除方法

      • 例如这样一个方法

      •    equalFn(a,b){return a===b}
        

        但是如果是一个对象,就不能这样简单对比,因为引用数据类型在栈中存放地址,每个对象地址不一样指向堆内存中实际对象的地址。

      • 可以直接暴力的转换成字符串

      •    equalFn(a,b){return JSON.stringify(a)===JSON.stringify(b)}
        

        但是如果把两个对象交换位置,就不能判断了

      • 可以直接用第三方库imumutable

      • 双向链表

      • 每个节点即能指向前一个(prev),有能指向后一个(next)

      • 插入值

      • 如果想在头部插入

      • insert(element,index){if(index>=0&&index<=this.count){const node=new Node(element)if(index===0){const current =this.headnode.next=currentthis.head=node
        }
        }
        

      • if(index === 0){ // 如果插入位置是链表头部

        这行代码检查是否要在链表的头部插入新节点。index 是插入位置的索引,如果它是0,意味着新节点应该成为新的头节点。

      • node.next = this.head; // 新节点的下一个节点设置为当前头节点

        这行代码将新节点(node)的 next 属性设置为当前的头节点(this.head)。这样,新节点就指向了原来的头节点,保持了链表的连续性。

        • node:新创建的节点,即将插入链表。
        • this.head:当前链表的头节点。
        • node.next = this.head:将新节点的 next 指针指向当前的头节点。
        • 如果想插入的位置不是头部

        • 思想:
        • 示例

          假设链表当前状态如下:

          复制

          Head -> A -> B -> C
          

          其中,A 是头节点,B 是第二个节点,C 是第三个节点。现在,我们想要在B和C之间插入一个新节点X:

        • previous = this.getNodeAt(1); // 获取B的引用
        • current = previous.next; // 获取C的引用
        • node.next = current; // 设置X的next指向C
        • previous.next = node; // 设置B的next指向X
        • 插入后的链表状态:

          复制

          Head -> A -> B -> X -> C
          

          总结

        • 当在链表的特定位置插入新节点时,需要找到该位置的前一个节点和当前节点。
        • 将新节点的next指向当前节点。
        • 将前一个节点的next更新为新节点。
        • 具体代码
        •     else{const previous=this.getNodeAt(index-1)//获取前一个节点const current =previous.next//让前一个节点指向新节点引用的位置node.next=current//把新建的节点放进去previous.next=node}
          

          完整插入代码

        • insert(element,index){if(index>=0&&index<=this.count){const node=new Node(element)if(index===0){const current=this.head//保护headnode.next=current//当前头节点作为新节点的下一个this.head=node//把新节点作为头节点}else{const previous=getNodeAt(index-1)const current=previous.nextnode.next=currentprevious.next=node}this.count++return true}return false
          }
          

          剩下几个简单的方法

        • isEmpty(){return this.size===0
          }
          size(){return this.count
          }
          gethead(){return this.head
          }
          

          双端链表

        • 还可以继承单链表的属性

        • class DoubleNode extends Node {constructor(element) {super(element); // 调用父类Node的构造函数this.prev = null; // 初始化DoubleNode特有的pre属性}
          }

        • super(element)调用Node类的构造函数,并将element参数传递给父类构造函数。这样,DoubleNode实例就继承了Node类的element属性

        • 之前封装的单向链表中很多方法需要重新封装

        • push

        •     push(){const node=new DoublyNode()//prev next
          if(this.head===null){this.head=nodethis.tail=node
          }else{this.tail.next=nodenode.prev=nodethis.tail=node
          }
          

          如果头部为空,就直接加

        • 头部不为空

        • 让链表尾部next与新节点连接,新节点prev指向尾部,再让尾部彻底等于新节点

        • insert

        • 不说了,思想全在图里
        •     insert(element,index){const node=DoublyLinked(element)let current=this.headif(index>=0&&index<=this.count){if(index===0){if(this.head===null)this.head=nodethis.tail=node}else{node.next=this.headthis.head.prev=nodethis.head=node}          }else if(index===this.count){current=this.tailcurrent.next=nodenode.prev=currentthis.tail=node}else{const previous=getNodeAt(index-1)current=previous.nextnode.next=currentcurrent.prev=nodeprevious.next=nodenode.prev=previous}this.count++return true}

          removeAt删除

        • 注意:index要小于this.count,因为count从0开始,最后的count值没有节点(和insert不同)

        • 按照索引值删除和insert思想差不多,需要注意的是如果让head的next指向下一个会出问题,因为曾经的尾部被head占了,所以之前让head直接赋值为head的next—— this.head=current.next

        •     removeAt(index){if(index>=0&&index<this.count){let current=this.headif(index===0){this.head=current.nextif(this.count===1){this.tail===null}else{this.head.prev=undefined}        }if(index===this.size()-1){let current =this.tailcurrent.prev=this.tailthis.tail.next=undefined}else{let previous=this.getNodeAt(index-1)current=previous.nextprevious.next=current.nextcurrent.next.prev=previous}this.count--return current.element}}
          

          remove

        • 按照数值删除和单链表方法一样

        • 循环链表

        • 就是让最后节点的next指向head,循环起来

        • insert插入

        • insert(element,index){let node=new DoublyLinked(element)let current=this.headif(index>=0&&index<=count){if(index===0){if(head===0){this.head=nodenode.next=this.head}else{node.next=currentcurrent = this.getNodeAt(this.size() - 1)//不能保证后面的节点指向head,下面解决,获得尾部元素this.head=node//current.next=this.head//让尾部元素next指向head,保证循环}}else{const previous=this.getNodeAt(index-1)current=previous.nextprevious.next=nodenode.next=current}this.count++
          return true}return false
          }
          

          removedAt——按索引删除

        • removeAt(index){
          if(index>=0&&index<count){let current=this.headif(index===0){if(this.size()===1){let last=this.getNodeAt(this.size()-1)this. head=this.head.nextlast.next=head}}else{let previous=this.getNodeAt(index-1)current=previous.nextprevious.next=current.next//不用怕删除后没有循环,因为被删的current的next就指向head}this.count--return current.element
          }
          }
          

          集合set

        • 无序且唯一的项组成

        • 因为对象的属性不能重复适合作为集合,下面我们用对象模拟

        • 属性和属性名都是一个内容,存100就是100:100所以想要操作某个元素直接this.items[element]就可以

        • 建一个class封装增删查改

        •     class kerwin{// constructor(){//   this.items={}// }items={}add(element){if(!this.has(element)){this.items[element]=elementreturn true}return false}delete(element){
          if(this.has(element)){delete this.items[element]return true
          }}has(element){
          return element in this.items}clear(){
          return this.items={}}size(){
          return Object.keys(this.items).length}values(){
          return Object.values(this.items)}}
          

          其中size方法用Object.keys()方法会返回一个包含对象所有自有属性(不包括原型链上的属性)的键(key)的数组。

        • 应用:检查数组中是否有重复元素

        •     var arr=[1,2,3,3,3,4]arr.forEach(items=>{myList.add(items)})
          

          Es6中的set属性

        • 迭代器

        • 符合迭代器的元素可以用多个next遍历,也可以用for...of遍历,也可以用展开运算符变为普通数组

        • 与上面我们自己封装的set不同在于,Es6的size是一个属性,我们是方法

        • 应用

        • 交集,并集,差集——从后端接收数据时候使用

        •     var mySetA=new Set([1,2,3])var mySetB=new Set([2,3,4])// 并集var mySetAnd=new Set([...mySetA],[...mySetB])// 交集——只有数组才有filter方法var mySetJiao=new Set([...mySetA].filter(item=>mySetB.has(item)))//差集var mySetJiao=new Set([...mySetA].filter(item=>!mySetB.has(item)))
          

          字典

        • 和集合很相似,但集合是【值,值】,字典【键,值】,键可以是对象,也可以是任意数据类型

        •     class Dictionary{table={}//将键转化为字符串tostrFn(item){if(item===null){return 'NULL'}else if(item===undefined){return 'UNDEFINDED'}else if(item==='string'||item instanceof String){return item}return JSON.stringify(item)}
          }

          tostrFn 

        • :使用 tostrFn 方法将 key 转换为一个字符串。这是因为在 JavaScript 对象中,键总是被转换为字符串。tostrFn 方法的执行步骤如下:

          • 如果 item(在这里是 key)是 null,返回字符串 'NULL'
          • 如果 item 是 undefined,返回字符串 'UNDEFINED'
          • 如果 item 是字符串或 String 对象的实例,直接返回该字符串。
          • 否则,使用 JSON.stringify 将 item 转换为字符串。
        • 检查键存在性:使用转换后的键字符串在 this.table 中查找。this.table 是一个对象,用于存储字典的键值对。

        • 返回结果:如果找到对应的键(即 this.table 中存在该键),则 this.table[this.tostrFn(key)] 不会是 nullhaskey 方法返回 true。如果没有找到,或者对应的值是 null,则返回 false

        • 注意:如果haskey 方法中检查的是 !== null,这意味着如果键存在但对应的值是 undefined 或其他非 null 值,它也会返回 true。所以改为!=null就可以了
        • set

        • 检查是否有键
        • 第一种方法
                //检查是否含有键haskey(key) {return this.table[this.tostrFn(key)] != null}set(key,value){if(key!==null&&value!==null){const tablekey=this.tostrFn(key)this.table[tablekey]=valuereturn true}return false}}
          

          这种方法将键存放的被转化后的字符串键名,所以另起一个方法二将value中存键+值,保证获取到最原始的键

        • 方法二

        •       set(key,value){if(key!==null&&value!==null){const tablekey=this.tostrFn(key)this.table[tablekey]=new ValuePair(key,value)return true}return false}}var mysseet=Dictionary()class ValuePair{constructor(key,value){this.key=keythis.value=value}}
          

          valuepair类创建一个实例对象保存一份原始的key,value

        • 其他方法

        •       get(key){const ValuePair=this.table[this.tostrFn(key)]return ValuePair ==null?undefined:ValuePair.value}remove(key){if(this.haskey(key)){delete this.table.tostrFn(key)return true}return false}keys(){return this.keyValues().map(item=>item.key)}values(){return this.keyValues().map(item=>item.value)}keyValues(){return Object.values(this.table)//Object.values() 只返回自有属性的值,不返回继承属性的值。}size(){return Object.keys(this.table).length}isEmpty(){return this.size===0}clear(){return this.table=null}forEach(cb){const ValuePair=this.keyValues()for(let i=0;i<ValuePair.length;i++){cb(ValuePair[i].key,ValuePair[i].value)}}

          散列表

        • 有上字典可以看到,由于set每次查找键都需要转化为JSON字符串很麻烦,并且遍历上万条大数据很消耗性能,所以散列表可以把键通过散列函数转换为一个数组作为索引,再从散列表中查找

        • set方法(就相当于push)

        •       set (key,value){if(key!=null&&value!=null){const position=111this.table[position]=ValuePair(key,value)return true}return false}
          

          需要有一个方法能给table设置类似position=111这个索引数字

        • hash表就派上用场了,将table中的键转化为字符串,

        1. 如果直接是数字就更好,不用转换,

        2. 一旦是字符串就用charCodeAt方法转化为ASCALl码

        3. ,防止hash值过大用取余

        4.       hashCode(key){const tablekey=this.tostrFn(key)for(let i=0;i<tablekey.length;i++){hash+=tablekey.charCodeAt(i)}return hash%37}//putset (key,value){if(key!=null&&value!=null){const position= hashCode(key)this.table[position]=ValuePair(key,value)return true}return false}
          

        • 其他方法——get remove

        •       get(key){
          const ValuePair=this.table[this.hashCode(key)]
          return ValuePair==null?undefined:ValuePair}remove(key){const deletePair=this.table[hash]const hash=this.hashCode(key)if(deletePair!==null){delete this.table[hash]return true}return false}
          

        • ES6中的map

        • const obj = {q: 235};
          map.set(obj, 'aaaaa');
          

          在这段代码中,obj是一个常量,引用了一个对象。当你调用map.set(obj, 'aaaaa')时,你是将obj这个引用作为键设置到了Map中。

          如果你尝试直接使用字面量对象作为键,如下所示:

          map.set({q: 123}, 'bbbbb');
          

          这里的问题在于,每次你使用{q: 123}这样的对象字面量时,你实际上是在创建一个全新的对象。在JavaScript中,对象是通过引用来比较的,而不是通过值。因此,即使两个对象字面量看起来相同(例如{q: 123}和另一个{q: 123}),它们却是不同的引用,因此被视为不同的键。总结来说,不能直接把{q: 123}传入map作为键,是因为每次这样写都会创建一个全新的对象,而Map是通过引用来识别键的。

        • wakemap——对象只能是键

        • 有垃圾回收机制,和map不同,一旦object被null,objet就不会占内存,也就不会被遍历

http://www.dtcms.com/wzjs/200421.html

相关文章:

  • 简历上作品展示网站链接怎么做凡科建站平台
  • 扶贫办网站建设北京关键词快速排名
  • 网站建设过程中什么最重要成都优化官网公司
  • 云南网站建设快速优化sem管理工具
  • 网站开发知识体系百度推广计划
  • 代做网站灰色关键词百度学术查重
  • 三个律师做网站合适吗太原seo网站管理
  • wordpress 反馈表温州企业网站排名优化
  • 河北提供网站制作公司电话武汉官网优化公司
  • 网站搜索条怎么做站长工具seo综合查询论坛
  • 网站上线多少钱专业地推团队
  • 网站怎么做关键词赛事资讯赛马资料
  • 哪里有网站建设企业免费下载百度到桌面
  • 个人做外贸网站平台有哪些深圳网络推广代运营
  • 未来做那个网站能致富青岛关键词优化seo
  • 深圳网站建设 公司网页关键词排名优化
  • ps做电商网站图标seo优化关键词排名优化
  • 遵义网站建设辽宁seo推广
  • 做有弹幕视频网站不属于网络推广方法
  • 可信的专业网站建设在线网页制作
  • 哈尔滨建设网官方网站推广接单平台
  • 具有口碑的柳州网站建设推荐沈阳网站关键词排名
  • 中国建筑招聘2022菏泽地网站seo
  • 中冶东北建设网站地推接单平台网
  • 石家庄房产信息网站石家庄seo网络推广
  • 宿迁网站建设公司关键词优化如何做
  • 女和女做网站百度账号免费注册
  • 新手如何做英文网站赚美元培训机构网站设计
  • 手机搭建电脑做的网站免费网站建站页面
  • 设计工作室取什么名字好南昌seo方案