这篇文章很长。但我相信这会澄清你的大部分疑问关于JavaScript继承的“原型”性质。甚至更多。请阅读整篇文章。
JavaScript基本上有两种数据类型
非对象物体
非对象
以下是非对象数据类型
一串数字(包括NaN和Infinity)布尔值(true,false)未定义
使用typeof运算符时,这些数据类型返回以下内容
typeof“string literal”(或包含字符串文本的变量)==“string”
typeof 5(或任何数字文本或包含数字文本或NaN或Infynity的变量)==“number”
typeof true(或false或包含true或false的变量)==“boolean”
typeof undefined(或未定义变量或包含未定义的变量)==“undefineed”
字符串、数字和布尔数据类型既可以表示为对象,也可以表示为非对象。当它们表示为对象时,其类型总是==“object”。一旦我们了解了对象数据类型,我们将回到这一点。
物体
对象数据类型可以进一步分为两种类型
函数类型对象非函数类型对象
Function类型对象是返回带有typeof运算符的字符串“Function”的对象。所有用户定义的函数和所有可以使用new运算符创建新对象的JavaScript内置对象都属于这一类。例如。
对象一串数字布尔型大堆类型化数组RegExp(RegExp)作用所有其他可以使用new运算符创建新对象的内置对象函数UserDefinedFunction(){/*用户定义的代码*/}
所以typeof(对象)==typeof(字符串)==typeof(数字)==typeof(布尔)==typeof(数组)==type-of(RegExp)==typeoft(函数)==typesof(UserDefinedFunction)==“函数”
所有Function类型对象实际上都是内置JavaScript对象Function的实例(包括Function对象,即递归定义的对象)。就好像这些对象是按以下方式定义的
var Object= new Function ([native code for object Object])
var String= new Function ([native code for object String])
var Number= new Function ([native code for object Number])
var Boolean= new Function ([native code for object Boolean])
var Array= new Function ([native code for object Array])
var RegExp= new Function ([native code for object RegExp])
var Function= new Function ([native code for object Function])
var UserDefinedFunction= new Function ("user defined code")
如上所述,Function类型对象可以使用new运算符进一步创建新对象。例如,object、String、Number、Boolean、Array、RegExp或UserDefinedFunction类型的对象可以使用
var a=new Object() or var a=Object() or var a={} //Create object of type Object
var a=new String() //Create object of type String
var a=new Number() //Create object of type Number
var a=new Boolean() //Create object of type Boolean
var a=new Array() or var a=Array() or var a=[] //Create object of type Array
var a=new RegExp() or var a=RegExp() //Create object of type RegExp
var a=new UserDefinedFunction()
这样创建的对象都是非函数类型的对象,并返回它们的typeof=='object'。在所有这些情况下,对象“a”无法进一步创建对象使用运算符new。所以以下是错误的
var b=new a() //error. a is not typeof==='function'
内置对象Math的类型为==“object”。因此,新运算符不能创建Math类型的新对象。
var b=new Math() //error. Math is not typeof==='function'
还要注意,Object、Array和RegExp函数可以创建一个新对象,而无需使用运算符new。然而,以下这些不适用。
var a=String() // Create a new Non Object string. returns a typeof==='string'
var a=Number() // Create a new Non Object Number. returns a typeof==='number'
var a=Boolean() //Create a new Non Object Boolean. returns a typeof==='boolean'
用户定义的函数是特殊情况。
var a=UserDefinedFunction() //may or may not create an object of type UserDefinedFunction() based on how it is defined.
由于函数类型对象可以创建新对象,因此它们也被称为构造函数。
每个构造函数/函数(无论是内置的还是用户定义的)在定义时都会自动具有一个名为“prototype”的属性,其值默认设置为对象。此对象本身有一个名为“constructor”的属性,默认情况下该属性引用构造函数/函数。
例如,当我们定义一个函数
function UserDefinedFunction()
{
}
自动发生以下情况
UserDefinedFunction.prototype={constructor:UserDefinedFunction}
此“prototype”属性仅存在于Function类型对象中(并且从不在非函数类型对象中)。
这是因为当创建一个新对象时(使用new操作符),它会继承Constructor函数当前原型对象的所有财产和方法,即在新创建的对象中创建一个内部引用,该对象引用Constructtor函数当前原型所引用的对象。
在对象中创建的用于引用继承的财产的“内部引用”称为对象的原型(它引用由Constructor的“prototype”属性引用的对象,但与之不同)。对于任何对象(函数或非函数),都可以使用object.getPrototypeOf()方法进行检索。使用此方法可以跟踪对象的原型链。
此外,创建的每个对象(函数类型或非函数类型)都有一个“构造函数”属性,该属性继承自构造函数函数的原型属性引用的对象。默认情况下,此“构造函数”属性引用创建它的构造函数(如果构造函数的默认“原型”未更改)。
对于所有Function类型对象,构造函数总是函数function(){}
对于非函数类型的对象(例如Javascript内置数学对象),构造函数是创建它的函数。对于Math对象,它是函数object(){}。
在没有任何支持代码的情况下,上面解释的所有概念都有点难以理解。请逐行阅读以下代码以了解概念。尝试执行它,以便更好地理解。
function UserDefinedFunction()
{
}
/* creating the above function automatically does the following as mentioned earlier
UserDefinedFunction.prototype={constructor:UserDefinedFunction}
*/
var newObj_1=new UserDefinedFunction()
alert(Object.getPrototypeOf(newObj_1)===UserDefinedFunction.prototype) //Displays true
alert(newObj_1.constructor) //Displays function UserDefinedFunction
//Create a new property in UserDefinedFunction.prototype object
UserDefinedFunction.prototype.TestProperty="test"
alert(newObj_1.TestProperty) //Displays "test"
alert(Object.getPrototypeOf(newObj_1).TestProperty)// Displays "test"
//Create a new Object
var objA = {
property1 : "Property1",
constructor:Array
}
//assign a new object to UserDefinedFunction.prototype
UserDefinedFunction.prototype=objA
alert(Object.getPrototypeOf(newObj_1)===UserDefinedFunction.prototype) //Displays false. The object referenced by UserDefinedFunction.prototype has changed
//The internal reference does not change
alert(newObj_1.constructor) // This shall still Display function UserDefinedFunction
alert(newObj_1.TestProperty) //This shall still Display "test"
alert(Object.getPrototypeOf(newObj_1).TestProperty) //This shall still Display "test"
//Create another object of type UserDefinedFunction
var newObj_2= new UserDefinedFunction();
alert(Object.getPrototypeOf(newObj_2)===objA) //Displays true.
alert(newObj_2.constructor) //Displays function Array()
alert(newObj_2.property1) //Displays "Property1"
alert(Object.getPrototypeOf(newObj_2).property1) //Displays "Property1"
//Create a new property in objA
objA.property2="property2"
alert(objA.property2) //Displays "Property2"
alert(UserDefinedFunction.prototype.property2) //Displays "Property2"
alert(newObj_2.property2) // Displays Property2
alert(Object.getPrototypeOf(newObj_2).property2) //Displays "Property2"
每个对象的原型链最终可以追溯到object.prototype(它本身没有任何原型对象)。以下代码可用于跟踪对象的原型链
var o=Starting object;
do {
alert(o + "\n" + Object.getOwnPropertyNames(o))
}while(o=Object.getPrototypeOf(o))
各种对象的原型链工作如下。
每个Function对象(包括内置Function对象)->Function.prototype->Object.prototype->null简单对象(由新的Object()或{}创建,包括内置的Math对象)->Object.prototype->null使用新的或Object.create创建的对象->一个或多个原型链->Object.prototype->null
要创建没有任何原型的对象,请使用以下方法:
var o=Object.create(null)
alert(Object.getPrototypeOf(o)) //Displays null
人们可能会认为,将构造函数的prototype属性设置为null将创建一个原型为null的对象。然而,在这种情况下,新创建的对象的原型被设置为object.prototype,其构造函数被设置为函数object。以下代码演示了这一点
function UserDefinedFunction(){}
UserDefinedFunction.prototype=null// Can be set to any non object value (number,string,undefined etc.)
var o=new UserDefinedFunction()
alert(Object.getPrototypeOf(o)==Object.prototype) //Displays true
alert(o.constructor) //Displays Function Object
本文摘要如下
有两种类型的对象功能类型和非功能类型只有函数类型的对象才能使用运算符new创建新对象。这样创建的对象是非函数类型的对象。非函数类型对象无法使用运算符new进一步创建对象。默认情况下,所有函数类型对象都具有“prototype”属性。此“prototype”属性引用了一个对象,该对象具有默认引用Function类型对象本身的“构造函数”属性。所有对象(函数类型和非函数类型)都有一个“构造函数”属性,默认情况下该属性引用创建它的函数类型对象/构造函数。内部创建的每个对象都引用创建该对象的构造函数的“prototype”属性。该对象称为创建对象的prototype(与它引用的函数类型对象“prototype“属性不同)。这样,创建的对象可以直接访问Constructor的“prototype”属性(在创建对象时)引用的对象中定义的方法和财产。可以使用object.getPrototypeOf()方法检索对象的原型(以及继承的属性名称)。事实上,这种方法可以用于导航对象的整个原型链。每个对象的原型链最终都会追溯到object.prototype(除非对象是使用object.create(null)创建的,在这种情况下,对象没有原型)。typeof(new Array())==“object”是由语言设计的,而不是Douglas Crockford指出的错误将构造函数的原型属性设置为null(或undefined、number、true、false、string)不会创建具有null原型的对象。在这种情况下,新创建的对象的原型设置为object.prototype,其构造函数设置为函数object。
希望这有帮助。