javascript中有三种基本数据类型,字符串(string),数值(number),布尔值(boolean),其余全是对象。
alert(typeof 'asdf');//string alert(typeof 22);//number alert(typeof true);//boolean alert(typeof new function(){});//object
基本数据类型在需要时会自动包装成对象类型,完成后再拆装为基本类型。
包装过程:
alert(typeof new String('asdf'));//object alert(typeof new Number(22));//object alert(typeof new Boolean(true));//object将对象转换为基本类型则是通过这样的方式:通过调用对象的valueOf()方法来取得对象的值,如果和上下文的类型匹配,则使用该值。如果valueOf取不到值的话,则需要调用对象的toString()方法,而如果上下文为数值型,则又需要将此字符串转换为数值。
var obj=new function(){}; alert(obj.__proto__.__proto__.__proto__);//null alert(obj.__proto__);//[object Object] alert(obj.__proto__.__proto__);//[object Object]函数对象的__proto__属性
function func(){var a=1;return 'adf';}; alert(typeof func);//function alert(func instanceof Function);//true alert(func.__proto__.__proto__.__proto__);//null alert(func.__proto__);//function(){} alert(typeof func.__proto__);//function alert(func.__proto__ instanceof Function);//false alert(func.__proto__.__proto__);//[object Object]
函数的__proto__属性很奇怪,是function类型但不是Function实例。
调用对象上的一个方法,由于方法在JavaScript对象中是对另一个函数对象的引用,因此解释器会在对象中查找该属性,如果没有找到,则在其内部对象__proto__属性上搜索,由于__proto__属性与对象本身的结构是一样的,因此这个过程会一直回溯到发现该属性,则调用该属性,否则,报告一个错误。
__proto__属性是在new操作中产生的。
var p = new ClassA ();
以上创建对象过程可以用以下过程模拟:
var p = {}; ClassA.apply(p); p.__proto__= ClassA.prototype;
也就是说对象的原型是其构造函数的prototype属性。这样就很好理解用原型实现继承的过程了。
构造函数的prototype是用其创建的对象的原型。