Execution Context of Methods in Go vs JavaScript

huangapple go评论91阅读模式
英文:

Execution Context of Methods in Go vs JavaScript

问题

以下是两个代码片段 - 一个是Go语言的,另一个是JavaScript的 - 本质上做着相同的事情。

// Go

package main    

import "fmt"

type Engine struct {
  bootTimeInSecs int
}

func (e *Engine) Start() {
  fmt.Printf("Engine starting in %s seconds ...", e.bootTimeInSecs)
}

type Start func() 

type BenchmarkSuite struct {
  workloads []string
  start Start 
}

func main() {
  engine := Engine{10}
  benchmarkSuite := BenchmarkSuite{workloads: []string{}, start: engine.Start}
  benchmarkSuite.start()
}

输出

Engine starting in 10 seconds ...

// JavaScript

function Engine(bootTimeInSecs) {
    this.bootTimeInSecs = bootTimeInSecs
}

Engine.prototype.constructor = Engine
Engine.prototype.Start = function() {
  console.log("Engine starting in " + this.bootTimeInSecs + " seconds ...")
}

function BenchmarkSuite(workloads, start) {
    this.workloads = workloads
    this.start = start
} 

BenchmarkSuite.prototype.constructor = BenchmarkSuite

engine = new Engine(10)
benchmarkSuite = new BenchmarkSuite([], engine.Start)
benchmarkSuite.start()

输出

Engine starting in undefined seconds ...

我知道JavaScript的解决方法,但这不是问题。为什么JavaScript决定不保留函数的原始执行上下文?

英文:

Below are two code snippets - one in Go and the other in JavaScript - essentially doing the same thing.

// Go

package main    

import "fmt"

type Engine struct {
  bootTimeInSecs int
}

func (e *Engine) Start() {
  fmt.Printf("Engine starting in %s seconds ...", e.bootTimeInSecs)
}

type Start func() 

type BenchmarkSuite struct {
  workloads []string
  start Start 
}

func main() {
  engine := Engine{10}
  benchmarkSuite := BenchmarkSuite{workloads: []string{}, start: engine.Start}
  benchmarkSuite.start()
}

Output

Engine starting in 10 seconds ...

// JavaScript

function Engine(bootTimeInSecs) {
    this.bootTimeInSecs = bootTimeInSecs
}

Engine.prototype.constructor = Engine
Engine.prototype.Start = function() {
  console.log("Engine starting in " + this.bootTimeInSecs + " seconds ...")
}

function BenchmarkSuite(workloads, start) {
    this.workloads = workloads
    this.start = start
} 

BenchmarkSuite.prototype.constructor = BenchmarkSuite

engine = new Engine(10)
benchmarkSuite = new BenchmarkSuite([], engine.Start)
benchmarkSuite.start()

Output

Engine starting in undefined seconds ...

I know the workaround in JavaScript, but that's not the question. Why did JavaScript decide not to retain the original execution context of a function?

答案1

得分: 1

在JavaScript中,当你将对象engine传递给BenchmarkSuite构造函数时,函数并没有绑定到该对象。

你需要显式地将对象绑定到函数上。你需要做的是:

benchmarkSuite = new BenchmarkSuite([], engine.Start.bind(engine))

bind()的最简单用法是创建一个函数,无论如何调用它,都会使用特定的this值。新的JavaScript程序员常犯的一个错误是从对象中提取一个方法,然后在以后调用该函数,并期望它使用原始对象作为它的this(例如,在基于回调的代码中使用该方法)。然而,如果不特别注意,原始对象通常会丢失。使用原始对象创建一个绑定函数,可以很好地解决这个问题。

你可以参考这里了解更多信息。

function Engine(bootTimeInSecs) {
    this.bootTimeInSecs = bootTimeInSecs
}

Engine.prototype.constructor = Engine
Engine.prototype.Start = function() {
  console.log("Engine starting in " + this.bootTimeInSecs + " seconds ...")
}

function BenchmarkSuite(workloads, start) {
    this.workloads = workloads
    this.start = start
} 

BenchmarkSuite.prototype.constructor = BenchmarkSuite

engine = new Engine(10)
benchmarkSuite = new BenchmarkSuite([], engine.Start.bind(engine))
benchmarkSuite.start()
英文:

Here in javascript the function is not bind to the object engine when you pass the object to BenchmarkSuite constructor.

You have to explicitly bind the object to the function.
This is what you have to do

benchmarkSuite = new BenchmarkSuite([], engine.Start.bind(engine))

> The simplest use of bind() is to make a function that, no matter how it is called, is called with a particular this value. A common mistake for new JavaScript programmers is to extract a method from an object, then to later call that function and expect it to use the original object as its this (e.g. by using that method in callback-based code). Without special care however, the original object is usually lost. Creating a bound function from the function, using the original object, neatly solves this problem

You may refer here for more
<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

function Engine(bootTimeInSecs) {
    this.bootTimeInSecs = bootTimeInSecs
}

Engine.prototype.constructor = Engine
Engine.prototype.Start = function() {
  console.log(&quot;Engine starting in &quot; + this.bootTimeInSecs + &quot; seconds ...&quot;)
}

function BenchmarkSuite(workloads, start) {
    this.workloads = workloads
    this.start = start
} 

BenchmarkSuite.prototype.constructor = BenchmarkSuite

engine = new Engine(10)
benchmarkSuite = new BenchmarkSuite([], engine.Start.bind(engine))
benchmarkSuite.start()

<!-- end snippet -->

huangapple
  • 本文由 发表于 2017年1月12日 14:40:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/41606653.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定