我对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_1
和foo_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
?
答案 0 :(得分:4)
为什么test.prototype的结果是空对象?
所有函数都有一个prototype
属性,最初引用一个空对象。
定义:( resig)
原型在整个JavaScript中用作方便的手段 定义将自动定义的属性和功能 应用于实例对象。
您设置对象的prototype
值,而不是test
功能。
- 每个对象 - 都继承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!")
这条引人注目的线条可以让你让一个玩家不在人身上(而且你会看到该玩家是一个人的实例!):
答案 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;最后)