"Object.call" 是什么意思?

8
function bb_graphics_GraphicsContext(){
    Object.call(this);
    this.bbdevice=null;
    this.bbmatrixSp=0;
    this.bbix=1.000000;
    this.bbiy=0;
    this.bbjx=0;
    this.bbjy=1.000000;
    this.bbtx=0;
    this.bbty=0;
    this.bbtformed=0;
    this.bbmatDirty=0;
    this.bbcolor_r=0;
    this.bbcolor_g=0;
    this.bbcolor_b=0;
    this.bbalpha=0;
    this.bbblend=0;
    this.bbscissor_x=0;
    this.bbscissor_y=0;
    this.bbscissor_width=0;
    this.bbscissor_height=0;
    this.bbmatrixStack=new_number_array(192);
}

Object.call(this) 是什么意思?


1
您可能希望明确表示,您想知道为什么构造函数(即“bb_graphics_GraphicsContext”函数)要对其自身的 this 引用这样做。 - Pointy
它被认为是构造函数。但如果是这样,必须在函数外部调用。 - miqbal
在我的答案末尾添加了额外的评论,以便了解它的作用,并提供为什么要这样做的思考。 - Paul Bruno
也许提供更多的上下文会有所帮助。bb_graphics_GraphicsContext 是在什么时候和如何被调用的?目前你所得到的最好答案大多是推测。 - Hemlock
5个回答

13

JavaScript中的函数是完整的对象。当它们作为参数传递给另一个函数时,它们不会保留它们的作用域。因此,在下面的代码中...

var obj1 = {
    property1: "blah",
    method1: function () {
        alert(this.property1);
        // do stuff
    }
 };

 function func1 (passedFunction) {
     passedFunction();
     // do other stuff
 }

 func1(obj1.method1);

...func1会调用obj1.method1,但它不会弹出obj1property1值,因为我们只是传递了函数对象,而不是它的this上下文。这就是callapply发挥作用的地方。它们允许您注入范围,告诉函数this的含义将是什么。以下示例有效:

var obj1 = {
    property1: "blah",
    method1: function () {
        alert(this.property1);
        // do stuff
    }
 };

 function func1 (passedObject, passedFunction) {
     passedFunction.call(passedObject);
     // do other stuff
 }

 func1(ob1, obj1.method1);
现在,我们通过调用call并将要用作this的对象传递给它,强制或明确告诉obj1.method1其上下文是什么。 callapply几乎相同,只是它们如何处理调用的函数的其他参数不同。有关更多信息,请参阅MDN上的这些文章:callapplyFunction
所有这些都说过了,bb_graphics_GraphicsContext是一个构造函数。(你可能已经猜到了。)你可以使用new关键字调用它:var obj1 = new bb_graphics_GraphicsContext();。当它到达函数的第1行时,它会获取this对象,并调用通用Object构造函数,显式地将新对象this(在bb_graphics_GraphicsContext构造函数中)注入为Object构造函数的this。我认为这个函数/构造函数的编写者这样做是为了确保在bb_graphics_GraphicsContext中新创建的对象获得所有基本Object的方法。但我不知道为什么这是必要的,因为如果你使用new关键字调用bb_graphics_GraphicsContext,它自然会获取所有这些属性。

1
所有这些都是完全正确的,但仍然没有回答Object构造函数的使用者为什么要这样做的问题。 - Pointy
有人想要重新定义 Object 吗? - DrStrangeLove
我不完全确定在JavaScript中是否可能。等一下...刚刚在Safari(Mac上)尝试了一下。是的,确实可能,但我怀疑任何人都不会想要这样做。 - Paul Bruno

0

虽然在这里表达的方式中,Object.call 可能什么也不做,但是这个概念可能很重要。基本上,在 Node.js 文档 中你将看到关于继承的示例:

const util = require('util');
const EventEmitter = require('events');

function MyStream() {
  EventEmitter.call(this);
}

util.inherits(MyStream, EventEmitter);

util.inherits 会使一个新的 MyStream 继承 (拥有与) EventEmmiter 相同的原型。如果我们只是希望 MyStream 可以访问通过 EventEmmiter 原型继承来的函数,那么这可能已经足够了。但是如果在构建时传递了变量呢?如果我们有:

function MyObject() {
    this.code = "2nV_ahR";
}

在这种情况下,当 MyObject 实例化时,将传递 code 变量。因此,子类需要传递:
function MySubObject() {
    MyObject.call(this);
}

为了继承code变量,call接受一个参数来设置this变量。因此,当我执行var o = new MySubObject()时,在MySubObject内部的this指向o,然后将其传递给call方法,这样当MyObject执行this.code = ...时,实际上是将code传递给了o

0

1
在这种情况下,“特定函数”指的是Object构造函数本身。 - Pointy

0
这个代码除了浪费资源和内存分配之外什么都不做。
如果 Object.call(this) 被分配给函数构造器 bb_graphics_GraphicsContext 的一个变量或属性,
this.myObject = Object.call(this)
那么在这种情况下,你得到的是一个空对象“不保留所提供的上下文”。
function MyConstructor(){
    this.test01 = 0;
    var b = Object.call(this); // similar to b = {}; or b = new Object()
    console.log(b); // log object 
    console.log(b.test); // log undefined
    this.test = 1;
}

var myObject = new MyConstructor();

console.log(myObject, window.test01)

-2
每个 JavaScript 函数都有一个 toString()call()apply()
this odetocode.com article 上阅读更多相关信息。

3
知道了。我想了解这种情境下会发生什么。这个关键字指的是什么?在执行Object.call(this);之后会发生什么? - DrStrangeLove
它变成了一个递归函数。 - miqbal
@miqbal 嗯...什么?它并没有将任何东西转换为递归函数;那甚至是什么意思? - Pointy
@Pointy,有什么区别,函数a() { a(); var b = 0; } - miqbal
这并不是 OP 中正在发生的事情,完全不是。你在那里的例子实际上是一个无限递归的错误;OP 中的代码只是调用了 Object 构造函数。这只是对一个不同函数的普通函数调用。 - Pointy
确切的递归错误。但是JS中的构造函数不像你说的那样工作。他必须在函数外部使用"new"。 - miqbal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接