4

我有一个关于 javaScript 函数的问题。考虑以下两个函数定义:

    // run time definition 
    var foo_1 = function () {
        console.log("I ma foo 1"); 
    }
    // parse time definition 
    function foo_2 ()  {
        console.log("I ma foo 2"); 
    }

由于在 javaScript 中每件事都是一个对象,是否使用 namefoo_1foo_2前面的代码创建了两个新对象?如果是这样,它们的原型对象是什么?这些对象是什么时候创建的?

我也在努力理解var obj={}和 var之间的真正区别foo=function(){},两者都是对象,但第一个有 "type" Object,而第二个有 type function。它是否正确?

根据我的书“JavaScript 的优点”,每个新的文字对象都链接到Object.prototype默认情况下是一个空对象。为了验证这种行为,我尝试运行以下脚本:

Object.prototype
//Object {}
Object.prototype = { name: "This is an experiment"}; 
//Object {name: "This is an experiment"}
function test() { conosle.log("Test"); }
test.prototype;
//Object {}

为什么结果test.prototype是一个空对象?

最后,我想知道这些函数定义是否等同于以下代码:

   this.foo =  function() {
         console.log("I ma foo");
    }

如果有,是什么this

4

3 回答 3

4

为什么 test.prototype 的结果是一个空对象?

所有函数都有一个最初引用空对象prototype的属性。

定义 : (resig)

原型在整个 JavaScript 中被用作定义属性和功能的便捷方式,这些属性和功能将自动应用于对象实例

您设置Objectprototype的值而不是函数的值。test

在 JS - 每个对象 - 继承Object.prototype

如果您已根据需要将功能附加到Object.prototype- :

Object.prototype.name = function (){alert(1);}; 
function test() { console.log("Test"); }
var a = new test();
a.name();

它会提醒1

编辑

关于您的评论:

我们真正想要实现的是一个原型链,这样 Player 可以是 Person,Person 可以是 Mammal,Mammal 可以是 Animal,以此类推,一直到 Object。创建这样一个原型链的最佳技术是使用一个对象的实例作为另一个对象的原型:

SubClass.prototype = new SuperClass();

考虑这段代码:

function Person(){}

   Person.prototype.dance = function(){};

function Player(){}

   Player.prototype = new Person();     <------

var player = new Player();

assert(player instanceof Player,"player receives functionality from the Player prototype");
assert(player instanceof Person, "... and the Person prototype");
assert(player instanceof Object, "... and the Object prototype");
assert(typeof player.dance == "function", "... and can play!")

注意到的行是使您能够从人中创建玩家的原因(您会看到该玩家是人的一个实例!):

在此处输入图像描述

http://jsbin.com/oNixIMo/8/edit

于 2013-11-10T12:09:40.650 回答
1

我认为您对函数和对象的原型有些困惑,希望我能够澄清一下。

首先:

function foo_2 ()  {
    console.log("I ma foo 2"); 
}

这称为“函数声明”,其中:

var foo_1 = function () {
    console.log("I ma foo 1"); 
}

称为“函数表达式”。您可以在此处获得详细信息:https ://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions_and_function_scope#Function_constructor_vs._function_declaration_vs._function_expression以及Function构造函数示例。

由于在 javaScript 中每件事都是一个对象,在前面的代码中是否创建了两个名为 foo_1 和 foo_2 的新对象?

是的,它们是对象,如果你修改prototype链,你会影响它们:

Object.prototype.testName = "this is an experiment";

function test() {}

console.log(test.testName) // "this is an experiment"

但是test.prototype也是一个对象,所以如果你这样做:

console.log(test.prototype.testName) // "this is an experiment"

原因是您没有正确获取属性,这可能是因为是继承的,并且您正在使用的控制台(节点,浏览器)仅显示对象自己的属性(例如Object.keys),而没有抓取整个原型链。

这是主要原因,因为您不应该更改Object.prototype:您将影响几乎所有事情并且您无法预测后果。

我说“主要”是因为您可以创建实际上不继承自Object原型的对象。您可以使用Object.create或支持的非标准 _proto _

var foo = {};
console.log(foo.testName) // "this is an experiment"

var bar = Object.create(null);
console.log(bar.testName) // undefined

最后,我想知道这些函数定义是否等同于以下代码:

this.foo =  function() {
  console.log("I ma foo");
 }

这取决于this您执行此代码的时间。如果您在全局范围内执行代码,它们基本上是等效的,this全局对象也是如此(在浏览器中是window)。但是,有区别。使用此语法,您将能够删除foo属性,而在声明时您不能这样做。所以:

this.foo = function() {};
var bar = function() {};

delete foo // can be deleted;
delete bar // shouldn't be deleted;

请参阅:https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/delete

于 2013-11-10T12:26:42.403 回答
1

Yesvar fn = function(){};是 Function 类型

为什么 test.porototype 为空:因为它是 Function.prototype,而不是 Object.prototype

这是什么:在最后发布的链接中回答

您可以使用函数作为构造函数来创建对象:

var Person = function(name){
  this.name = name;
};
Person.prototype.walk=function(){
  this.step().step().step();
};

在示例中,Person 被称为构造函数,因为它是一个对象,您可以为其赋予属性,例如:Person.static="somthing"这对于与 Person 相关的静态成员非常有用,例如:

 Person.HOMETOWN=22;
 var ben = new Person("Ben");
 ben.set(Person.HOMETOWN,"NY");
 ben.get(Person.HOMETOWN);//generic get function what do you thing it'll get for ben?
 ben.get(22);//maybe gets the same thing but difficult to guess

当您使用 Person 创建实例时,您必须使用 new 关键字:

var bob = new Person("Bob");console.log(bob.name);//=Bob
var ben = new Person("Ben");console.log(bob.name);//=Ben

属性/成员name是特定于实例的,对于 bob 和 ben 是不同的

成员 walk 可用于所有实例(bob 和 ben 是 Person 的实例)

bob.walk();ben.walk();

因为在 bob(以及后来的 ben)上找不到 walk(),JavaScript 将在 Person.prototype 中查找它。bob 和 ben 都只有一个 walk 函数,但该函数的行为会有所不同,因为它在 walk 函数中使用this.

如果 ben 正在等待红灯,而您将调用 walk 并且 bob 处于绿灯,那么显然 ben 和 bob 会发生不同的事情,即使walkbob 和 ben 的操作完全相同,但this会引用当前对象(bob for鲍勃和本本)。

当我做类似的事情时,会发生跟踪成员ben.walk=22,即使 bob 和 benwalk将 22 分配给 ben.walk 不会影响 bob.walk。这是因为该语句将创建一个名为walkben 的成员并将其赋值为 22。当请求 bob.walk 时,您将获得 Person.prototype.walk 函数,因为walk在 bob 上找不到。然而,询问 ben.walk 会得到值 22,因为成员 walk 是在 ben 上创建的,并且由于 JavaScript 发现 walk on ben,它不会在 Person.prototype 中查找。

因此,当在实例上找不到成员时,JavaScript 引擎将查找构造函数的原型。那么 ben.hasOwnProperty 是从哪里形成的呢?实例 ben 没有它, Person.prototype 没有它。答案是有一个原型链,Person 的构造函数是 Function,所以当在 ben 或 Person.prototype 上找不到 hasOwnProperty 时,它会查找 Person 构造函数的原型(即 Funcition)。如果它在那里找不到hasOwnProperty(但它可以),那么它将查看Function的构造函数的原型(是Object)。

一切都应该从 Object.prototype 继承,除非你这样做Object.create(null,{})在我看来是个坏主意。您可以在 Object.prototype 上添加东西(也不是一个好主意),并且 JS 中的任何对象都将“继承”:

Object.prototype.yipee=function(){
  console.log("yipeee");
};

22..yipee();//logs yipeee
"hello".yipee();//logs yipee

现在您已经了解了它的基础知识,您可以查看以下内容:

https://stackoverflow.com/a/16063711/1641941(以“这个变量”开头)

于 2013-11-10T12:49:12.287 回答