首页 > 其他分享 >[AHK2] 向对象原型添加属性和方法

[AHK2] 向对象原型添加属性和方法

时间:2023-10-22 18:11:35浏览次数:47  
标签:index return AHK2 cb 添加 原型 数组 call fn

ahk和js十分相似,其中一点就是可以向本地对象添加自定义方法和属性。
下面的脚本向ahk的字符串,数组添加了许多方法,添加之后在使用上就和js更加相似了。

; This script is used to extend the methods of the ahk native object prototype

#Requires AutoHotkey v2.0
#SingleInstance Force

Undefined := ''

noop(*) {
}

; # String
DefProp := {}.DefineProp
DefProp("".base, "At", { call: _At_String })
DefProp("".base, "CharAt", { call: _CharAt })
DefProp("".base, "CharCodeAt", { call: _CharCodeAt })
DefProp("".base, "ToCharArray", { call: _ToCharArray })
DefProp("".base, "Concat", { call: _Concat_String })
DefProp("".base, "EndWith", { call: _EndWith })
DefProp("".base, "Repeat", { call: _Repeat })
DefProp("".base, "ToLowerCase", { call: _ToLowerCase })
DefProp("".base, "ToUpperCase", { call: _ToUpperCase })
DefProp("".base, "ToTitleCase", { call: _ToTitleCase })
DefProp("".base, "Length", { get: StrLen })
DefProp("".base, "IsString", { get: (*) => true })

; 返回指定位置的字符,如果是负数从字符串末尾开始。
_At_String(this, index) {
  charArr := this.ToCharArray()
  if index > 0
    return charArr[index]
  else if index < 0
    return charArr[this.Length + index + 1]
  else
    return Undefined
}
; 返回指定位置的字符,不接受负数。
_CharAt(this, index) {
  if index <= 0 || index > this.Length
    return Undefined
  charArr := StrSplit(this)
  return charArr[index]
}
; 返回指定位置的字符码元
_CharCodeAt(this, index) {
  char := this.CharAt(index)
  return Ord(char)
}
; 返回字符串的字符数组、
_ToCharArray(this) {
  return StrSplit(this)
}
; 将字符串参数连接到调用的字符串,并返回一个新的字符串。
_Concat_String(this, str*) {
  r := this
  for v in str {
    r .= v
  }
  return r
}
; 判断一个字符串是否以指定字符串结尾,如果是则返回 true,否则返回 false。
; 第二个参数指定预期结尾位置,如果字符串在该位置结束,返回 true,否则返回 false。
_EndWith(this, searchString, endPostion?) {
  sl := searchString.Length
  if IsSet(endPostion) {
    if sl < endPostion {
      target := SubStr(this, endPostion - sl + 1, sl)
      if target = searchString
        return true
    }
    return false
  } else {
    return searchString = SubStr(this, this.Length - sl + 1)
  }
}
; 构造并返回一个新字符串,其中包含指定数量的所调用的字符串副本,这些副本连接在一起。
_Repeat(this, count) {
  if count < 0
    throw Error('RangeError')
  count := Floor(count)
  loop count {
    r .= this
  }
  return r
}
_ToLowerCase(this) {
  return StrLower(this)
}
_ToUpperCase(this) {
  return StrUpper(this)
}
_ToTitleCase(this) {
  return StrTitle(this)
}

; # Array
arrProto := Array.Prototype
arrProto.DefineProp("Concat", { call: _Concat_Array })
arrProto.DefineProp("Peek", { call: _Peek })
arrProto.DefineProp("At", { call: _At_Array })
arrProto.DefineProp("Every", { call: _Every })
arrProto.DefineProp("Fill", { call: _Fill })
arrProto.DefineProp("Filter", { call: _Filter })
arrProto.DefineProp("Find", { call: _Find })
arrProto.DefineProp("FindIndex", { call: _FindIndex })
arrProto.DefineProp("FindLast", { call: _FindLast })
arrProto.DefineProp("FindLastIndex", { call: _FindLastIndex })
arrProto.DefineProp("ForEach", { call: _ForEach })
arrProto.DefineProp("DeepClone", { call: _DeepClone })
arrProto.DefineProp("Includes", { call: _Includes })
arrProto.DefineProp("Join", { call: _Join })
arrProto.DefineProp("Map", { call: _Map })
arrProto.DefineProp("Reduce", { call: _Reduce })
arrProto.DefineProp("ToString", { call: _ToString })
arrProto.DefineProp("Reverse", { call: _Reverse })
arrProto.DefineProp("ToReverse", { call: _ToReverse })
arrProto.DefineProp("Shift", { call: _Shift })

Array.DefineProp('From', { call: _From })

; 静态方法从字符串或数组创建一个新的**深拷贝**的数组实例。
_From(this, arrayLike, mapFn?) {
  if not (arrayLike is Array or arrayLike.isString)
    throw Error('invalid param')
  if IsSet(mapFn) {
    switch mapFn.MaxParams {
      case 1: fn := (v, *) => mapFn(v)
      case 2: fn := (v, index, *) => mapFn(v, index)
      default: throw Error('invalid callback function')
    }
  } else fn := (v, *) => v
  arr := []
  if arrayLike is Array {
    for v in arrayLike {
      arr.Push(fn(v, A_Index))
    }
  } else {
    arr := arrayLike.ToCharArray()
  }
  return arr
}
; 将两个或多个数组或值合并成一个新数组。
; 此方法不会更改现有数组,而是返回一个新数组。
_Concat_Array(this, value*) {
  r := this.DeepClone()
  for v in value {
    if value is Integer {
      r.Push(v)
    } else {
      for vv in v {
        r.push(vv)
      }
    }
  }
  return r
}
; 查看数组末尾元素
_Peek(this) {
  return this[this.Length]
}
; 方法接收一个整数值并返回该索引对应的元素,允许正数和负数。
; 负整数从数组中的最后一个元素开始倒数。
_At_Array(this, index) {
  return index > 0 ? this[index] : this[this.Length + index]
}
; 测试一个数组内的所有元素是否都能通过指定函数的测试。
; 它返回一个布尔值。
_Every(this, cb) {
  copy := this
  switch cb.MaxParams {
    case 1: fn := (v, *) => cb(v)
    case 2: fn := (v, index, *) => cb(v, index)
    case 3: fn := (v, index, arr) => cb(v, index, arr)
    default: throw Error('invalid callback function')
  }
  for v in copy {
    if !fn(v, A_Index, copy)
      return false
  }
  return true
}
; 用一个固定值填充一个数组中从起始索引(默认为 0)到终止索引(默认为 array.length)内的全部元素。
; 它返回修改后的数组。
_Fill(this, value, start?, end?) {
  l := this.Length
  if IsSet(start) {
    if IsSet(end) {
      end := end > l ? l : end
      start := start > end ? end : start
      d := end - start
    } else {
      d := start > l ? l : l - start
    }
    loop d + 1 {
      this[start + A_Index - 1] := value
    }
  } else {
    loop l {
      this[A_Index] := value
    }
  }
}
; 创建给定数组一部分的**深拷贝**(与js不同),其包含通过所提供函数实现的测试的所有元素。
_Filter(this, cb) {
  r := []
  switch cb.MaxParams {
    case 1: fn := (v, *) => cb(v)
    case 2: fn := (v, index, *) => cb(v, index)
    case 3: fn := (v, index, arr) => cb(v, index, arr)
    default: throw Error('invalid callback function')
  }
  for v in this {
    if fn(v, A_Index, this)
      r.Push(v)
  }
  return r
}
; 返回数组中满足提供的测试函数的第一个元素的值。否则返回 空。
_Find(this, cb) {
  for v in this {
    if cb(v)
      return v
  }
}
; 返回数组中满足提供的测试函数的第一个元素的索引。
; 若没有找到对应元素则返回 -1。
_FindIndex(this, cb) {
  for v in this {
    if cb(v)
      return A_Index
  }
  return -1
}
; 反向迭代数组,并返回满足提供的测试函数的第一个元素的值。
_FindLast(this, cb) {
  loop this.Length {
    if cb(v := this.Pop())
      return v
  }
}
; 反向迭代数组,并返回满足提供的测试函数的第一个元素的索引。
_FindLastIndex(this, cb) {
  l := this.Length
  loop l {
    if cb(this.Pop())
      return l - A_Index + 1
  }
  return -1
}
; 对数组的每个元素执行一次给定的函数。
_ForEach(this, cb) {
  switch cb.MaxParams {
    case 1: fn := (v, *) => cb(v)
    case 2: fn := (v, index, *) => cb(v, index)
    case 3: fn := (v, index, arr) => cb(v, index, arr)
    default: throw Error('invalid callback function')
  }
  for v in this {
    fn(v, A_Index, this)
  }
}
; 返回数组的深拷贝。
_DeepClone(this) {
  arr := []
  for v in this {
    arr.Push(v)
  }
  return arr
}
; 用指定分隔符连接数组元素。
; 返回一个字符串
_Join(this, separator?) {
  sep := IsSet(separator) ? separator : ','
  for v in this {
    if A_Index != this.Length
      r .= v sep
    else
      r .= v
  }
  return r
}
; 用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回 false。
_Includes(this, searchElement, fromIndex?) {
  if IsSet(fromIndex) {
    l := this.Length
    if fromIndex > 0 {
      if fromIndex > l
        return false
      i := fromIndex
    } else {
      if fromIndex < -l || fromIndex = 0
        return this.FindIndex((v) => v = searchElement) != -1
      i := l + fromIndex + 1
    }
    c := l - i + 1
    loop c {
      if this[i + A_Index - 1] = searchElement
        return true
    }
    return false
  } else {
    return this.FindIndex((v) => v = searchElement) != -1
  }
}
; 创建一个新数组,这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成。
_Map(this, cb) {
  switch cb.MaxParams {
    case 1: fn := (v, *) => cb(v)
    case 2: fn := (v, index, *) => cb(v, index)
    case 3: fn := (v, index, arr) => cb(v, index, arr)
    default: throw Error('invalid callback function')
  }
  res := []
  for v in this {
    res.push(fn(v, A_Index, this))
  }
  return res
}
; 对数组中的每个元素按序执行一个提供的 reducer 函数,每一次运行 reducer 会将先前元素的计算结果作为参数传入。
; 最后将其结果汇总为单个返回值。
_Reduce(this, cb, initialValue?) {
  l := this.Length
  if !l and !IsSet(initialValue)
    throw TypeError()
  else if !l and IsSet(initialValue) {
    return initialValue
  } else if l = 1
    return this[1]
  switch cb.MaxParams {
    case 1: fn := (p1, *) => cb(p1)
    case 2: fn := (p1, p2, *) => cb(p1, p2)
    case 3: fn := (p1, p2, p3, *) => cb(p1, p2, p3)
    case 4: fn := (p1, p2, p3, p4) => cb(p1, p2, p3, p4)
    default: throw Error('invalid callback function')
  }
  if IsSet(initialValue) {
    accumulator := initialValue + this[1]
    i := 1
  } else {
    accumulator := this[1]
    i := 0
  }
  loop l - i {
    accumulator := fn(accumulator, this[A_Index + i], A_Index + i, this)
  }
  return accumulator
}
; 返回字符串,包含数组地址及数组的元素
_ToString(this) {
  ptr := ObjPtr(this)
  prefix := '[ Array@' ptr '] ['
  suffix := ']'
  quote := '"'
  sep := ', '
  for v in this {
    content .= quote v quote sep
  }
  return prefix SubStr(content, 1, content.Length - 2) suffix
}
; 就地反转数组中的元素,并返回同一数组的引用。
_Reverse(this) {
  l := this.Length
  loop l / 2 {
    temp := this[A_Index]
    this[A_Index] := this[l - A_Index + 1]
    this[l - A_Index + 1] := temp
  }
  return this
}
; 反转数组中的元素,并返回新数组的引用。
_ToReverse(this) {
  l := this.Length
  arr := []
  loop l {
    arr.Push(this[l - A_Index + 1])
  }
  return arr
}
; 从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。
_Shift(this) {
  return this.RemoveAt(1)
}

; # Iterator
; 包装原生Enumrator对象。
; Usage:
;     iter := GetIterator([1, 2, 3, 4])
;     MsgBox iter.Next().key
;     MsgBox iter.Next().value
;     MsgBox iter.Next().done

GetIterator(source) {
  if source is Primitive
    throw TypeError('Expect an object but get the primitive type')
  iter := {}
  iter.DefineProp('Next', { call: Next })
  Next(*) {
    if source is Array or source is Map {
      static enum := source.__Enum()
    } else {
      static enum := source.OwnProps()
    }
    enum.call(&index, &value)
    done := false
    if not (IsSet(index) and IsSet(value))
      index := '', value := '', done := true
    return {
      key: index,
      value: value,
      done: done
    }
  }
  return iter
}

标签:index,return,AHK2,cb,添加,原型,数组,call,fn
From: https://www.cnblogs.com/refiz/p/17780790.html

相关文章

  • Figma(原型设计软件)官方下载 正版下载
    Figma中文版是一款专业强大的设计软件。Figma最新版还是一个现代化的钢笔工具。用矢量网络向任何方向绘制。不再需要合并或需要连接到路径的原点。Figma中文版拥有即时的弧线设计。使用Arc工具轻松设计时钟、手表屏幕或饼图。支持系统化设计。使用组件加快设计速度。快速编辑和覆盖......
  • CBV添加装饰器的三种方式
    fromdjango.viewsimportViewfromdjango.utils.decoratorsimportmethod_decorator"""CBV中django不建议你直接给类的方法加装饰器无论该装饰器能都正常给你都不建议直接加"""#@method_decorator(login_auth,name='get')#方式2(可以添加多个针对不同的方法加不同......
  • SpringBoot中给Tomcat添加过滤器
    SpringBoot中给Tomcat添加过滤器目录SpringBoot中给Tomcat添加过滤器一、引入二、Filter功能概述三、添加过滤器进行实操3.1、注解版3.2、配置版本四、原理探究4.1、解析过程4.2、如何添加到ServletContext中?五、总结一、引入JavaWeb组件Servlet提供了filter过滤功能,其功能是对......
  • 从零用VitePress搭建博客教程(5) - 如何自定义页面模板、给页面添加独有的className和
    接上一节:从零用VitePress搭建博客教程(4)–如何自定义首页布局和主题样式修改?上一节其实我们也简单说了自定义页面模板,这一节更加详细一点说明,开始之前我们要知道在vitePress中,.md的文件是可以直接编写vue的代码的。比如我们现在来自定义一个前端网址导航页面八、自定义一些......
  • MDT2013自动化部署Windows系统-启动映像添加
    添加启动映像:1:打开windows部署服务控制台,右键“启动映像”,选择“添加启动映像”:2:选择启动映像文件存放位置:MDT控制台更新的启动映像存放位置:Deploymentshare\Boot\目录下:3、输入映像名称和相应说明:4、确认选定映像摘要:5、完成启动映像添加:6、完成后视图如下:接下来为大家介绍的是WDS......
  • 设计模式-原型模式
    原型模式(PrototypePattern)是用于创建重复的对象,同时又能保证性能。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式是实现了一个原型接口,该接口用于创建当前对象的克隆。当直接创建对象的代价比较大时,则采用这种模式。例如,一个对象需要在一个高代价的......
  • uboot为LED添加DM驱动--Apple的学习笔记
    一,前言开始玩所有板子一般都是先点灯,比如我可以在汇编中点灯,可以在board_init中用writel写寄存器点灯,当我要进一步熟悉下设备树驱动模型,不管学习linux还是学习uboot这块我理解类似,所以我要通过添加设备树及配置开关来实现默认打开led0和led1的功能。二,实现的过程1,先有了dts信息,我从......
  • ABAP-SM30添加选择屏幕
    1*&---------------------------------------------------------------------*2*&ReportZRFI0303*&---------------------------------------------------------------------*4*&5*&---------------------------------------------------......
  • Chromium 通过IDL方式添加扩展API
    基于chromium103版本1.自定义扩展API接口chromium默认扩展api接口中有chrome.runtime.*,和chrome.send.*等,现在我们就仿照chrome.runtime方式来定义自己的接口,供给插件或者网页使用。其实chromium增加自定义api接口,在原生代码中添加有两种方式,一种是使用json定义,另外一种......
  • QT 菜单中添加Qcheckbox复选框
    //回放autowidget=newQWidget;{autocheckbox=newQCheckBox("回放");autolayout=newQHBoxLayout;layout->addWidget(checkbox);layout->setContentsMargins(5,1,5,1);widget->setLayout(l......