js原型

let arr = []
console.log(arr)
//[]
//   length: 0
//   __proto__: Array(0)
//     concat: ƒ concat()
//     constructor: ƒ Array()
//     copyWithin: ƒ copyWithin()
//     entries: ƒ entries()
//     every: ƒ every()
//     fill: ƒ fill()
//     filter: ƒ filter()
//     find: ƒ find()
//     findIndex: ƒ findIndex()
//     flat: ƒ flat()
//     flatMap: ƒ flatMap()
//     forEach: ƒ forEach()
//     includes: ƒ includes()
//     indexOf: ƒ indexOf()
//     join: ƒ join()
//     keys: ƒ keys()
//     lastIndexOf: ƒ lastIndexOf()
//     length: 0
//     map: ƒ map()
//     pop: ƒ pop()
//     push: ƒ push()
//     reduce: ƒ reduce()
//     reduceRight: ƒ reduceRight()
//     reverse: ƒ reverse()
//     shift: ƒ shift()
//     slice: ƒ slice()
//     some: ƒ some()
//     sort: ƒ sort()
//     splice: ƒ splice()
//     toLocaleString: ƒ toLocaleString()
//     toString: ƒ toString()
//     unshift: ƒ unshift()
//     values: ƒ values()
//     Symbol(Symbol.iterator): ƒ values()
//     Symbol(Symbol.unscopables): {copyWithin: true, entries: true, fill: true, find: true, findIndex: true, …}
// __proto__: Object

js创建的数组,隐式原型为Array

根据打印结果可知上文中创建的空数组,隐式原型(_proto_)正是Array,而Array中有push等方法

arr.push(1)
console.log(arr) // 1

使用arr.push,根据js原型链,实则是调用的Array中的.push方法

js原型就不在此做论述了,如果需要详细了解可以参考下列文章

深入理解JavaScript原型和闭包

那么上述过程在go中怎么实现呢

使用go简单实现上文中js的原型

go中的定义函数,函数名前的参数称为方法接收者

接收者有两种,一种是值接收者,一种是指针接收者

顾名思义,值接收者,是接收者的类型是一个值,是一个副本,方法内部无法对其真正的接收者做更改;指针接收者,接收者的类型是一个指针,是接收者的引用,对这个引用的修改直接影响真正的接收者

那么我们可以定义指针接收者函数,就可以对源数据进行修改

下文为go简单的代码实现js中的arr push方法

package main

import "fmt"

// 数组的_proto_,值为Value
type Array struct {
    Value []int
}

// 封装创建arr的function
func newArray(arr []int) *Array {
    proto := &Array{
        Value: arr,
    }
    return proto
}

// 封装js数组push api,指针接收者为Array
func (arr *Array) push(item int) {
    // go api中的追加slice数据(类似js中push操作)
    arr.Value = append(arr.Value, item)
}

func main() {
    // 通过封装的api创建slice(js数组),为初始化之后的结构体Array
    arr := *newArray([]int{1, 2, 3})
    // 打印数组中的值
    fmt.Println(arr.Value)
    // [1 2 3]

    // 调用封装的push方法,方法内为go写法
    arr.push(4)
    // 打印push之后的数组
    fmt.Println(arr.Value)
    // [1 2 3 4]
}
两种语言差异化导致代码不是很严谨,但思路应该没啥问题,请大佬轻喷
Last modification:September 22, 2020
If you think my article is useful to you, please feel free to appreciate