💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
# proto ES中的对象都保留着原型的引用。 当对象访问一个自身没有的属性时,会试图从原型中访问该属性。 而原型也是一个对象。如果在原型中仍然没找到该属性,将试图从原型的原型中访问…… ![](https://box.kancloud.cn/df85b837a0c393ab30d41c273a8c7cc6_992x474.jpg) 因为其链表的结构,所以被称为原型链。 chrome浏览器环境中的原型是在对象属性上显式的实现,以下的例子有通过对__proto__属性访问改变对象的原型。 但这在真正的编程环境中是不被推荐的,因为不是所有的浏览器都有__proto__的实现。 ~~~ var foo = {}; var prototype = { name: 'I in prototype.' }; foo.__proto__ = prototype; console.dir(foo.name);//I in prototype. ~~~ # Function 对一个Function类对象使用**new**关键字,可以构造一个指定原型的对象。 而这种方式所指定的原型,是该Function类对象的**prototype**。 ~~~ var classA = function () { }; classA.prototype = { name: 'I in prototype.' }; var foo = new classA(); console.dir(foo.name);//I in prototype. ~~~ 这种使用一个函数对象A构造出另一个对象B的行为,被称为类的实例化。 A为B的类,B为A的实例。 使用**instanceof**关键字可以判断一个对象是否为一个函数对象的实例。 ~~~ foo instanceof classA;//true ~~~ 实际上instanceof判断的是,一个对象的原型链中的其中一个原型是否为另一个函数对象的prototype。 ~~~ var mock = function () { }; mock.prototype = classA.prototype; foo instanceof mock;//true ~~~ PS:该实例确实能通过原型链使用该类提供的属性,所以instanceof的语义并没有发生变化,A instanceof B仍然是判断A是否为B的实例。 值得一提的是Function对象由其本身构造。 ~~~ Function.__proto__ === Function.prototype;//true;不恰当的例子。 ~~~ 而Function对象的prototype则是由Object对象构造。 ~~~ Function.prototype.__proto__ === Object.prototype;//true;不恰当的例子 ~~~ # Object 因为对象都有其原型,而原型无论来自哪个函数对象,也改变不了其是对象的事实,最终都会指向能构造一般对象的Object的prototype。 所以才有那么一句话,ES所有对象都派生于Object。 ~~~ Function instanceof Object;//true Number instanceof Object;//true new Number() instanceof Object;//true //.. ~~~ 那么Object.prototype的原型是什么?原型链到此就结束了。在实现上,Object.prototype的原型是null值,用来作为原型链的结束符号。 ~~~ Object.prototype.__proto__ === null;//true;不恰当的例子 ~~~ # 构造函数 用来构造对象的函数对象,他的函数本身被称为构造函数。 构造函数可以接受参数,在执行时能通过this关键字对构造出来的对象进行操作。 ~~~ var classA = function (name) { this.name = name; }; var foo = new classA('foo'); console.dir(foo); ~~~ ![](https://box.kancloud.cn/67b03b56c3b7296321f543cbbda1803a_218x58.jpg) new classA的执行步骤可以看做是: 1. 新构造一个对象。 2. 将对象的原型指向classA的prototype。 3. 使对象调用classA这个构造函数。 4. 返回该对象。 以下用代码模仿这个过程。 ~~~ var classA = { construct: function () { }, prototype: {}, new: function () { var obj = {};//1. 新构造一个对象。 obj.__proto__ = this.prototype;//2. 将对象的原型指向classA的prototype。 this.construct.apply(obj, arguments);//3. 使对象调用classA这个构造函数。 return obj;//4. 返回该对象。 } }; var foo = classA.new() foo.__proto__ === classA.prototype;//true ~~~ 同时,用代码模仿原型链的访问。 ~~~ var __index = function (obj, key) { //尝试访问键为key的属性。 if (obj[key]) { return obj[key]; } else { //存在原型,尝试从原型中访问。 if (obj.__proto__) { return __index(obj.__proto__, key); } else { return undefined; } } }; ~~~