JavaScript中的函数可以作为Object的实例调用吗?

Can functions in JavaScript be called as an instance of Object?

我最近被介绍学习 JavaScript,当我经历 prototype 概念时,我真的很困惑。我阅读和理解的一切都变得混乱。

让我们直接通过..

我有两个关于函数和对象的问题。

问题一:

JS中的函数可以有(key, value)对属性吗?如果是这样,密钥的数据类型可能是什么?因为在一个Object中,propertykey只能是StringObject类型,在某些特殊情况下Symbol.

问题二:

函数内部是如何求值的?它们是否转换为对象?

function sample () {
  // code goes here
}

let myFunc = new Function(,,);

谢谢

现在这是一个很好的问题,它会让很多人感到困惑。首先是 javascript 中构造函数和原型的概念 所以

function A() {
console.log("A")
}

if you console.log(typeof(A)) // "function"

现在A也有原型了

console.log("Aprototype", A.prototype) 

那将是一个对象 该原生对象有一个 属性 proto

console.log(A.prototype.__proto__)

这将是父原型。当前原型从中继承。这个父原型也将有一个构造函数,那就是你的函数构造函数

console.log("parentConstructor", A.prototype.__proto__.constructor)

现在这个父 Protype 还有一个 proto,它链接到对象函数构造函数

console.log("parent parent __proto__", A.prototype.__proto__.__proto__)

它的构造函数是你的对象构造函数。

这就是您能够获得新对象的原因

var t = new Object()

看看我们如何像构造函数一样调用它。

这就是原型 javascript 的样子:)

您可以随意向函数添加属性,因为 JavaScript 函数是对象。在您提供的用于创建函数的两种语法中,您都会得到一个(函数)对象。

添加属性示例:

function counter() {
    console.log(++counter.count);
}
counter.count = 0; // create a property on the function object

// Call the function several times
counter();
counter();
counter();

由于函数是对象,因此适用相同的限制:属性 名称是字符串。价值观可以是任何东西。属性未排序。

我最好的建议是跳入 Chrome 控制台并在那里玩。在他们的地方安装砖块的真正好方法。

Can functions in JS have (key, value) pair of property in it? If so, what might me the data type of the key? Because In an Object, the key of the property can be only of the types String, Object and in some special cases Symbol.

当然可以。但是您误解了有关 Object 的一些内容作为键。你可以这样做:

var obj = {};
var key = {};
obj[key] = "Smthg";

但这会起作用,因为 key 会被字符串化。所以 obj[key] 将被转换为 obj["[object Object]"]。测试一下:

var obj = {};
var key = {};
obj[key] = "key1";
obj["[object Object]"] = 'key2';

console.log(obj[key]);

如您所见,无论您使用多少对象作为键,它们都会相互覆盖。

How are the functions evaluated internally? Are they converted to objects?

JS 是 OOP 语言——一切都是对象(除了一些原语等)。所以这意味着有许多不同的对象。它们相互继承了一些东西,否则就会有一个 GIANT 对象,所有这些属性都是有界的,并且等待时间无穷无尽,以加载您的第一个 "Hello World" 应用程序。

我学习 JS 的最佳工具可能是 console.dir() 方法(如果在控制台模式下,则只是 dir(someVar))。

创建对象 - var f = new Function()dir(f) 看看它是什么以及它的原型是什么等等。

问题 1 的答案:

是的,您可以在一个函数中使用键:值对,但该函数称为 constructor。例如:

function Car(make, model, year) {
   this.make = make;
   this.model = model;
   this.year = year;
}

在 ES6 中:您可以在 class 中使用 constructor() 函数存储相似的 key:value 对。例如:

 constructor(make, modal, year) { // constructor syntactic sugar
   this.make = make;
   this.model = model;
   this.year = year;
}

key 的数据类型取决于您在 key 中存储的值的类型。在我们的示例中,如果我将字符串值存储在 this.model 中,模型键的数据类型将为字符串,如果我将年份存储为数字,则 this.year 的数据类型将为 number .

问题 2 的答案

要了解函数的内部工作原理,您需要了解 execution context。要了解执行上下文,您必须阅读 David 的这篇文章。简单地说:

每次调用函数时,都会创建一个新的执行上下文。但是,在 JavaScript 解释器内部,对执行上下文的每次调用都有两个阶段:

创作阶段

[when the function is called, but before it executes any code inside]: Create the Scope Chain. Create variables, functions and arguments. Determine the value of "this".

激活/代码

Execution Stage: Assign values, references to functions and interpret / execute code.

看来您的总体问题是“什么是函数”。

是的,函数是对象*。这就是为什么他们是 first-class 公民。它们就像任何其他值一样。就像其他对象一样,它们可以具有属性(您可能熟悉 f.callf.bind 等)。

函数与其他对象的区别在于它们有一个内部[[Call]]属性(用户代码无法访问内部属性,它们被使用在规范中定义对象的内部 state/behavior)。

[[Call]] 属性 包含函数体中代码的一些表示。调用函数时执行的就是这段代码

函数运行还需要其他内部属性,但 [[Call]] 是最重要的。用于判断对象是否可调用

原型 主要与功能无关。原型是一般适用于对象的概念。它们也不是很复杂:原型只是一个对象。使一个对象成为原型的原因是另一个对象通过它的 internal [[Prototype]] 属性 引用了它。那么我们可以说“这个对象是另一个对象的原型”。


其他语言的工作原理类似。例如,Python 允许您通过实施神奇的 def __call__: 方法使 classes 的实例可调用。


*:JavaScript有七种数据类型:

  • 布尔值
  • 人数
  • 字符串
  • 未定义
  • 符号
  • 对象

前六种是所谓的“原始”数据类型。