为什么Nodejs中不能给call, apply声明变量?

为什么Nodejs中不能给call, apply声明变量?

var getTypeStr = Object.prototype.toString.call;
getTypeStr({}); // 你认为结果是什么?

为什么呢?

6 回复

当然可以。让我们来详细探讨一下这个问题,并通过示例代码进行说明。

问题背景

在Node.js中,callapply 是 JavaScript 函数对象的内置方法,用于改变函数执行时的上下文(即 this 的值)。通常情况下,callapply 用于调用一个函数并传入特定的参数或参数数组。

示例代码

var getTypeStr = Object.prototype.toString.call;

console.log(getTypeStr({})); // 输出: "[object Object]"

问题核心

问题是,当我们尝试将 Object.prototype.toString.call 赋值给一个变量 getTypeStr 后,再调用 getTypeStr,它不会像我们预期的那样工作。原因在于 Object.prototype.toString.call 是一个绑定到特定对象的方法调用,而当我们将其赋值给一个新变量时,这个绑定关系被打破了。

原因分析

Object.prototype.toString 是一个函数,但当我们使用 call 方法时,它实际上是在 Object.prototype 上的一个方法调用。当我们将 Object.prototype.toString.call 赋值给 getTypeStr 变量时,我们只是复制了这个方法的引用,而不是复制它的上下文(即 this 指向的对象)。

因此,当我们调用 getTypeStr({}) 时,this 在内部不再是 Object.prototype,而是默认指向全局对象(在浏览器中是 window,在 Node.js 中是 global),这会导致错误的结果。

解决方案

为了正确地使用 callapply,我们应该在调用时显式地传递上下文:

var getTypeStr = function (obj) {
    return Object.prototype.toString.call(obj);
};

console.log(getTypeStr({})); // 正确输出: "[object Object]"

或者,我们可以直接使用箭头函数来保持正确的上下文:

const getTypeStr = obj => Object.prototype.toString.call(obj);

console.log(getTypeStr({})); // 正确输出: "[object Object]"

通过这种方式,我们可以确保 this 在调用 Object.prototype.toString.call 时始终指向正确的对象。这样,无论是在浏览器还是在 Node.js 环境中,我们都能得到预期的结果。


toString.call 他是基于构造函数去调用的, 也应该算是函数内部的. 所以你根本没有必要纠结这个问题. 他就是这么特殊.

根据ecma-262的规范,call方法需要在func对象上调用。当IsCallable(func)为false的时候,会抛出TypeError。所以chrome中的错误是:TypeError: undefined is not a function

http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.4.4

var type = function(obj) {
         var map = {
             '[object Array]': 'array',
             '[object Object]': 'object',
             '[object String]': 'string',
             '[object Number]': 'number',
             '[object Boolean]': 'boolean',
             '[object Null]': 'null',
             '[object Function]': 'function'
         };
         var t = Object.prototype.toString.call(obj);
         return map[t];
     }

根据你代码的意思,你可能是需要类似于这种功能。希望对你有帮助。

炒冷饭的bind

在Node.js中,callapply 是 JavaScript 函数对象的方法,用于调用函数并传入指定的对象作为上下文。但是,将它们赋值给变量时,不会改变其行为或功能。

对于你提到的代码:

var getTypeStr = Object.prototype.toString.call;
getTypeStr({});

这里的问题在于,Object.prototype.toString.call 需要两个参数:一个是上下文对象(通常是某个对象),另一个是要获取类型字符串的目标对象。直接将 call 方法赋值给 getTypeStr 变量后,只传递了一个参数 {},这会导致错误。

为了正确使用 call 方法,你需要提供上下文对象。例如:

var getTypeStr = Object.prototype.toString.call.bind(Object.prototype.toString);
console.log(getTypeStr({})); // "[object Object]"

在这个例子中,我们使用了 bind 方法来固定 call 方法的第一个参数为 Object.prototype.toString。这样,当我们调用 getTypeStr 时,它会以正确的上下文对象进行调用。

如果只是想获取一个对象的类型字符串,可以直接使用:

var getTypeStr = function(obj) {
    return Object.prototype.toString.call(obj);
};

console.log(getTypeStr({})); // "[object Object]"

以上代码定义了一个函数 getTypeStr,该函数接受一个参数 obj 并返回该对象的类型字符串。这种方式更加直观且易于理解。

回到顶部