javascript:函数和对象...?

IT技术 javascript function object
2021-02-09 14:02:57

您可以将函数作为对象调用吗?例如:

function Tip(txt){      
    this.content = txt;  
    this.shown = false;  
}

和:

var tip = new Tip(elem.attr('title'));

我的问题:

  1. 你能调用new一个函数,比如一个对象吗?
  2. 使“this”的使用成为可能,因为我们那个函数用作对象?
6个回答

你正在寻找这个constructor概念。

JavaScript中的所有函数都是对象,可用于创建对象:

function make_person(firstname, lastname, age) {
    person = {};
    person.firstname = firstname;
    person.lastname = lastname;
    person.age = age;
    return person;
}
make_person("Joe", "Smith", 23);
// {firstname: "Joe", lastname: "Smith", age: 23}

但是,为了创建特定类型的新对象(也就是说,继承原型,具有构造函数等),函数可以引用this如果使用new运算符调用它,则它将返回一个包含所有对象的对象this在函数中定义的属性-this在这种情况下引用我们正在创建的新对象。

function make_person_object(firstname, lastname, age) {
    this.firstname = firstname;
    this.lastname = lastname;
    this.age = age;
    // Note, we did not include a return statement
}

make_person之间要注意的主要区别make_person_object是调用new make_person()(而不是简单的make_person())不会做任何不同的事情......两者都会产生相同的对象。然而,make_person_object()没有new操作符的情况下调用将定义this当前this对象的属性(通常window如果您在浏览器中操作。)

因此:

var Joe = make_person_object("Joe", "Smith", 23);
console.log(Joe); // undefined
console.log(window.firstname) // "Joe" (oops)

var John = new make_person_object("John", "Smith", 45);
console.log(John); // {firstname: "John", lastname: "Smith", age: 45}

此外,正如@RobG 指出的那样,这种做事方式会创建对我们创建的每个“人”prototype属性的引用make_person_object这使我们能够在事后向人员添加方法和属性:

 // Assuming all that came before
make_person_object.prototype.full_name = "N/A";
make_person_object.prototype.greet = function(){ 
    console.log("Hello! I'm", this.full_name, "Call me", this.firstname); 
};
John.full_name // "N/A"
John.full_name = "John Smith"; 
make_person_object.full_name // Still "N/A"
John.greet(); // "Hello! I'm John Smith Call me John"

make_person_object约定俗成的构造函数像大写、单数化和“名词化”(因为没有更好的术语)——因此我们会有一个Person构造函数,而不是一个make_person_object可能被误认为是普通函数的 a 。

也可以看看:

你遗漏了最重要的部分:构造函数引用的新对象this从构造函数的原型继承属性。
2021-03-18 14:02:57
@RobG——我做到了我已经更新了答案以包含一些示例 - 感谢您帮助使其变得更好!
2021-04-04 14:02:57
很棒的答案。真的很棒。涵盖了要做什么,然后教我如何理解它。我读过的每个问题都在后面的部分中得到了回答。谢谢!!
2021-04-10 14:02:57

每个函数都有一个对this. 如果调用Tip(),this将引用全局对象。如果调用new Tip(),则会创建一个引用 Tip.prototype 的新对象,this并将引用该新对象。

您不能new在对象上使用,例如new {}throws TypeError: object is not a function如果您指的是new Object()那么有效,因为它Object是一个函数。

是的。在 JavaScript 中,从技术上讲,一切都是对象。当您使用 new 时,它会创建一个 Tip 对象的实例,然后像调用构造函数一样调用 Tip 函数。

如果你想向 Tip 对象添加函数,你应该像这样将它们添加到 Tip 的原型中:

Tip.prototype.getContent = function() {
    return this.content;
};

如果你有,然后你做:

var tip = new Tip("this  is my content.");
alert(tip.getContent());

它会显示一条消息,说“这是我的内容”。

但是,如果对象具有功能实现,则只能使用 new。所以这行不通:

var Tip = { content: txt, show: false };
var tipObj = new Tip();

近 8 年(2008-2016 年)我一直在努力理解这些概念(作为对象的函数、原型对象、__proto__ 属性、构造函数属性)。首先,在多次阅读第 6、8、9 章后,我开始使用 David Flanagan “JavaScript Definitive Guide 5/6th ed” 4-5 年;这对我来说没有任何意义,但在互联网上挣扎之后,我可以将函数(具有属性的典型 C++ 函数)作为对象进行管理;因为对象也可以有方法。幸运的是,在 2015 年的第 7 年,我开始编写 Wrox Nicholas C. Zakas “Professional JavaScript for Web Developers 3rd ed”第 6,7 章;理解以上四个概念真的很有帮助。传统上,在 C/C++/C# 中,函数被认为是修改对象;或者换句话说,它们是为“做某事”而设计的 其中,对象用于维护全局运行上下文的状态,并使用更改其自身对象状态的方法。那么如果函数可以是一等对象,那么为什么对象不能像函数呢?

这里的主要关键问题应该是 WHY ?为什么不是像“关联函数”或“链式参数”这样的单一概念实体?这是我的理解:浏览器 exe 是一个单线程应用程序,这个 exe 控制调用具有预定义作用域链的 JS 解释器(有些类似于带有参数的命令字符串);现在在运行时,JS 引擎(不是解释器)以提升方式加载代码(因为没有 main 方法,所以提升了定义良好的关键字代码及其调用)。在这个提升的代码中,如果函数不被视为对象,那么它们必须在单独的调用上下文(范围链外)中维护,这在 c/c++/c#(多线程和无限内存的 bcoz)中很容易实现,但在 JS 中则不然. 因此“对链式对象的待办事项” 使java脚本函数作为第一类对象。事实上 JS 对象也做同样的事情;唯一的区别是“调用对象”不在对象中,而“调用函数”是有意义的链接上下文。函数也可以被认为是“一堆带有地址链接(链)的汇编语言指令的变量”。链接部分是故事的另一面,如顶部->底部链接(原型对象)与底部->顶部链接(__proto__ 属性)与对象蓝图->对象实例(构造函数属性)。几个月前,我发现下图有助于理解链接。函数也可以被认为是“一堆带有地址链接(链)的汇编语言指令的变量”。链接部分是故事的另一面,如顶部->底部链接(原型对象)与底部->顶部链接(__proto__ 属性)与对象蓝图->对象实例(构造函数属性)。几个月前,我发现下图有助于理解链接。函数也可以被认为是“一堆带有地址链接(链)的汇编语言指令的变量”。链接部分是故事的另一面,如顶部->底部链接(原型对象)与底部->顶部链接(__proto__ 属性)与对象蓝图->对象实例(构造函数属性)。几个月前,我发现下图有助于理解链接。

http://judis.me/wordpress/wp-content/uploads/2015/08/JavaScriptDiagram.png “JS 对象模型”

#1 :有一个名为 Function(大写 F)的对象

var f = new Function("x", "y", "返回 x*y;");

对于#2:“this”根据调用模式(如 Douglas Crockford 所称)的不同而不同。Crockford 说有 4 种模式(方法模式、函数模式、构造器模式和“应用”模式)

不确定这与 OP 有什么关系(也许只是我)。可能想在downvotes涌入之前澄清。
2021-03-28 14:02:57
@Adam:它没有调用 eval 。如果您仔细阅读,答案与他的第一个问题有关。
2021-04-11 14:02:57
哦,它确实不调用 eval。但出于同样的原因,这很糟糕:-)
2021-04-11 14:02:57
调用 eval 并没有比创建函数经常做的更强大。似乎也与问题无关。
2021-04-14 14:02:57