1。函数是新对象的构造函数
当您调用new FuncName 时,函数充当构造函数,内部this 的值指向正在构造的对象(而不是函数本身)。当您删除 new 时,this 变为 undefined,回退到全局对象(除非您处于严格模式)。
2。函数也是对象
每个函数都是Function 的一个实例,所以函数本身就是对象并且可以有自己的属性。这些属性不能在函数体内使用this.propName 访问,只能使用funcName.propName。那是因为函数中的this从不函数对象本身(除非你强迫它是,bind、call 或 apply)。
我希望以上两个主题都能帮助您了解函数的工作原理。至于您的最后一个问题:Crockford 的createObject 是实现继承的另一种方式,基本上与Object.create 在符合ES5 的浏览器中所做的一样。它允许一个对象直接从另一个对象继承,而不需要您手动创建一个新的构造函数,设置它的prototype 属性(这是一个函数对象的属性示例),并使用new 创建一个实例。 Crockford 更喜欢这一点,并表示他不再使用 new 来支持这种方法。
针对您在聊天中提出的问题,这里尝试通过示例来解释什么是函数以及它们的作用。
函数可以只是...函数
你打电话给他们,他们做某事:
function alertThis(what) {
alert(what)
}
alertThis("alerting something");
你也可以给它们传值,让它们返回值
function timesTwo(num) {
return num * 2;
}
timesTwo(2); // 4
它们可以被传递和返回任何东西,包括对象......
function createPerson(firstName, lastName) {
return {
firstName : firstName,
lastName : lastName
}
}
var john = createPerson('John', 'Doe');
john.lastName; // "Doe"
...和其他功能:
function timesN(n) {
return function(num) {
return n * num;
}
}
var timesThree = timesN(3);
timesThree(5); // 15
函数是对象
函数可以像任何普通对象一样被传递和返回。那是因为它们是对象。像任何对象一样,它们可以具有属性:
function countCalls() {
countCalls.timesCalled++;
}
countCalls.timesCalled = 0;
countCalls();
countCalls();
countCalls.timesCalled; // 2
函数的一个非常重要的默认属性是prototype。这是一个特殊的属性,我们会看到原因。
函数可以作为新对象的构造函数
函数的行为类似于常规 OO 语言中的类构造函数。 当使用new 调用时,它们会创建某个“类”的新对象。这个新对象在函数内部被称为this,并自动返回:
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
var john = new Person('John', 'Doe');
john.firstName; // "John"
john instanceof Person; // true
...除非你故意返回别的东西:
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
var fakePerson = {
firstName : firstName,
lastName : lastName
};
return fakePerson;
}
var notPerson = new Person('John', 'Doe');
notPerson.firstName; // "John"
notPerson instanceof Person; // false
// Note: the object called 'this' inside the function is created, but
// after the function is called there is no outside reference to it.
构造函数创建的对象知道是谁创建的,并且可以看到它们的prototype属性
回到真人:
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
// Add something to the Person prototype
Person.prototype.sayHi = function() {
return "hi, I'm " + this.firstName;
}
var john = new Person('John', 'Doe');
john.sayHi(); // "Hi, I'm John"
john.constructor; // Person
对象john 可以sayHi(),因为它可以访问其构造函数的prototype 属性中的所有内容。但是它不能直接看到Person的其他属性(只能通过自己的constructor属性):
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
Person.timesCalled++;
// There is no 'this.timesCalled', only Person.timesCalled
}
Person.timesCalled = 0;
var john = new Person('John', 'Doe');
john.timesCalled; // undefined - john cannot be called, Person can
john.constructor.timesCalled; // 1