在javaScript中声明函数时使用的原型是什么

时间:2013-11-10 11:56:30

标签: javascript function

我对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中,每个东西都是一个对象,所以在前面的代码中创建了两个名为foo_1foo_2的新对象?如果是这样,他们的原型对象是什么以及何时创建这些对象?

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

根据我的书“JavaScript the good part”,每个新的文字对象都链接到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

3 个答案:

答案 0 :(得分:4)

  

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

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

定义:( resig)

  

原型在整个JavaScript中用作方便的手段   定义将自动定义的属性和功能   应用于实例对象。

您设置对象prototype值,而不是test功能。

JS中的

- 每个对象 - 都继承Object.prototype

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

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

它会提醒1

修改

关于你的评论:

我们真正想要实现的是一个原型链,以便玩家  可以是一个人,一个人可以是一个哺乳动物,一个哺乳动物可以是一个  动物等等,一直到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!")

这条引人注目的线条可以让你让一个玩家不在人身上(而且你会看到该玩家是一个人的实例!):

enter image description here

<强> http://jsbin.com/oNixIMo/8/edit

答案 1 :(得分: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

答案 2 :(得分:1)

var fn = function(){};属于Funcion

为什么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创建实例时,必须使用新关键字:

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

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

可以在所有实例上使用成员遍历(bob和ben是Person的实例)

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

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

如果本正在等待红灯而且你会引发行走并且鲍勃处于绿灯状态,那么即使walk对于鲍勃和{b}具有完全相同的效果,明显会出现不同的情况。 ben但this将引用当前对象(bob为bob,ben为ben)。

当我做ben.walk=22之类的事情时会发生阴影成员,即使bob和ben共享walk,对ben.walk的22分配也不会影响bob.walk。这是因为该语句将在ben上创建一个名为walk的成员,并为其赋值22.当要求bob.walk时,您将获得Person.prototype.walk函数,因为walk在bob上找不到。然后要求ben.walk将获得值22,因为成员行走已在ben上创建,因为JavaScript发现在Ben上行走它不会在Person.prototype中查找。

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

一切都应该继承自Object.prototype,除非你做Object.create(null,{}),在我看来这是一个坏主意。你可以在Object.prototype上添加东西(也不是一个好主意),JS中的任何对象都会继承&#34;继承&#34;的是:

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

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

现在你掌握了它的基础知识,你可以查看以下内容:

https://stackoverflow.com/a/16063711/1641941(以&#34开头;此变量&#34;最后)