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

时间:2018-01-17 13:38:30

标签: javascript ecmascript-6 javascript-objects prototypal-inheritance

我最近开始学习JavaScript,当我完成prototype概念时,我感到非常困惑。我阅读和理解的一切都让人感到困惑。

让我们直截了当..

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

问题1:

JS中的函数可以有(key,value)属性对吗?如果是这样,那么密钥的数据类型可能是什么?因为在对象中,key的{​​{1}}只能是[{1}},property类型,在某些特殊情况下String

问题2:

内部评估的功能如何?它们是否转换为对象?

Object

Symbol

由于

5 个答案:

答案 0 :(得分:2)

似乎你的整体问题是“什么是功能”。

是的,功能是对象*。这就是他们一等公民的原因。它们就像任何其他价值一样。就像其他对象一样,它们可以具有属性(您可能熟悉f.callf.bind等)。

功能与其他对象的区别在于它们具有内部 [[Call]]属性(无法从用户代码访问内部属性,它们在规范中用于定义内部状态/行为对象)。

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

函数需要其他内部属性,但[[Call]]是最重要的属性。它用于确定对象是否可调用

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

其他语言的工作方式相似。例如,Python允许您通过实现魔术def __call__:方法来使类的实例可调用。

*:JavaScript中有七种数据类型:

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

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

答案 1 :(得分:1)

您可以随意向函数添加属性,因为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();

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

答案 2 :(得分:1)

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

  

JS中的函数可以有(key,value)属性对吗?如果是这样,   我可能是密钥的数据类型?因为在一个对象中,关键   属性的类型只能是String,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]);

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

  

内部评估的功能如何?他们转变为   对象

JS是OOP语言 - 一切都是对象(除了一些原语等)。这意味着有许多不同的对象。并且他们互相继承了一些东西,否则会有一个GIANT对象,所有这些属性都有界限,无休止的等待时间来加载你的第一个“Hello World”应用程序。

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

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

答案 3 :(得分:1)

回答问题1:

是的,您可以在函数内部使用key:value对,但该函数名为constructor。例如:

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

在ES6中:您可以在类中使用constructor()函数存储类似的键:值对。例如:

 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解释器中,对执行上下文的每次调用都有两个阶段:

创作阶段

  

[调用函数时,但在执行之前   内部的任何代码]:创建范围链。创建变量,函数   和论点。确定"这个"的值。

激活/代码

  

执行阶段:分配值,对函数的引用和解释   /执行代码。

答案 4 :(得分:0)

现在这是一个很好的问题,可能会让很多人感到困惑。首先,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__)

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

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

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

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

,它的构造函数是你的Object构造函数。

这就是为什么你能够获得新对象

var t = new Object()

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

这就是典型的javascript:)