JavaScript进阶:深入理解原型与原型链
2017-08-27 01:01
471 查看
JavaScript进阶:深入理解原型与原型链
一、普通对象和函数对象
对象可以分为普通对象和函数对象,Object和Function是ECMAScript是自带函数对象。看如下代码:
在上面例子中ob1、2、3为普通对象。fun1、2为函数对象,因为fun1、fun2归根结底是通过new
Function()创建的。
二、原型对象
在JavaScript中,每当定义一个对象的时候,对象中都包含一些预定义的属性。其中每个函数对象都会有一个prototype属性,这个属性指向函数的原型对象。这里有一个特别重要的特性:每个对象(普通对象和函数对象)都有_proto_属性,但是只有函数对象才有prototype属性
看如下代码:
如果不好理解,可以把上面代码转换一下:
上面提到对象可分为普通对象和函数对象,这里原型对象便是普通对象了。可以这样认为原型对像就是Person.prototype。
三、原型对象中的construtor属性
上述原型对象Person.prototype,这里只给了他一个name属性,默认情况下所有的原型对象自动获得一个construtor属性。construtor属性是一个指针,指向它的构造函数,在例子中指向Person。基本构造函数有Number()、Boolean()、String()、Function()、Object()等等。如果通过构造函数创建新对象,这种创建方法都有一个共同点,那就是代码格式为:var
【对象】 = new 【构造函数】。
看看如下代码:
这里严格相等的原因是实例person1的constructor属性和Person.prototype的constructor属性是同一样东西,正确地说person1的constructor属性继承于原型对象Person.prototype。
四、_proto_
JS在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做_proto_的内置属性,用于指向创建它的构造函数的原型对象。
对象person1有一个_proto_属性,创建它的构造函数是Person,构造函数的原型对象是Person.prototype,所以
person1._proto_ = Person.prototype;
五、检验对原型链的理解
1、person1_proto_是什么?
解:意思是实例对象person1的构造函数的原型对象,首先person1的构造函数是Person,然后Person的原型对象是Person.prototype。所以person1_proto
= Person.prototype。
2、Person_proto_是什么?
解:因为Person在创建时是通过function Person(){}的形式创建的,所以Person的构造函数是Function,而Function的构造函数是Function.prototype。所以Person_proto
= Function.prototype。
3、Person.prototype._proto_是什么?
解:在前面提过Person.prototype是一个普通对象,所以他的构造函数是Object,Object的原型对象是Object.prototype;
4、Object._proto_是什么?
解:Object和Person一样是函数对象,所以两者答案一样。
5、Object.prototype._proto_是什么?
解:这个比较特殊,结果为null,因为null位于原型链的顶端。
六、函数对象
所有函数对象,包括:Number、Boolean、String、Function、Object的_proto_都是Function.prototype。
ECMAScript中内置构造器有12个,这里列举了8个构造器。剩下的如Global不可以访问,Arguments仅在函数调用时由JS引擎创建,Math、JSON是以对象形式存在的。他们的构造函数是Object,_proto_是Object.prototype。如下代码:
所有的构造器都继承于Function.prototype,甚至包括根构造器Object和Function自身。
Function.prototype也是唯一一个类型为Function的原型对象。其他构造器的原型对象的类型都是Object。看如下代码:
这里可能有一个疑问,Function.prototype是一个Function,那么Function.prototype的构造函数应该是Function,Function.prototype._proto_岂不是Function.prototype,这样就进入一个死循环。其实ESMASript中Function.prototype._proto是Object.prototype,而Object.prototype._proto_则是原型链最顶端的null。
六、构造器的继承
在Object的原型对象里面有着如下图中的所有属性,
而当我们创建一个数组时:
var arr = new Array();
arr继承了Array.prototype的所有属性和方法,如下图:
但是却没有找到constructor,按照道理来说,每一个函数对象的原型对象都应该有constroctor才对。原因是,因为Array.prototype是一个对象,Array.prototype继承了Object.prototype的所有属性和方法,所以Array.prototype最终是拥有constructor属性的。
一、普通对象和函数对象
对象可以分为普通对象和函数对象,Object和Function是ECMAScript是自带函数对象。看如下代码:
function fun1 () {}; var fun2 = new Function(); var ob1 = {}; var ob2 = new Object(); var ob3 = new fun1(); console.log (typeof Function); //Function console.log(typeof Object); //Function console.log(typeof fun1); //Function console.log(typeof fun2); //Function console.log(typeof ob1); //Object console.log(typeof ob2); //Object console.log(typeof ob3); //Object
在上面例子中ob1、2、3为普通对象。fun1、2为函数对象,因为fun1、fun2归根结底是通过new
Function()创建的。
二、原型对象
在JavaScript中,每当定义一个对象的时候,对象中都包含一些预定义的属性。其中每个函数对象都会有一个prototype属性,这个属性指向函数的原型对象。这里有一个特别重要的特性:每个对象(普通对象和函数对象)都有_proto_属性,但是只有函数对象才有prototype属性
看如下代码:
function Person() { Person.prototype.name = "tom"; Person.prototype.sayname = function () { alert (this.name); } } var person1 = new Person(); var person2 = new Person(); alert(person1.name == person2.name); //true,因为两个实例的name属性,都是同一属性,即原型对象中的name。
如果不好理解,可以把上面代码转换一下:
Person.propertype = { name = "tom"; sayname = function () { alert (this.name); }}
上面提到对象可分为普通对象和函数对象,这里原型对象便是普通对象了。可以这样认为原型对像就是Person.prototype。
三、原型对象中的construtor属性
上述原型对象Person.prototype,这里只给了他一个name属性,默认情况下所有的原型对象自动获得一个construtor属性。construtor属性是一个指针,指向它的构造函数,在例子中指向Person。基本构造函数有Number()、Boolean()、String()、Function()、Object()等等。如果通过构造函数创建新对象,这种创建方法都有一个共同点,那就是代码格式为:var
【对象】 = new 【构造函数】。
Person.prototype.constructor == Person;//true
看看如下代码:
console.log(Person.prototype.constructor === person1.constructor); //true
这里严格相等的原因是实例person1的constructor属性和Person.prototype的constructor属性是同一样东西,正确地说person1的constructor属性继承于原型对象Person.prototype。
四、_proto_
JS在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做_proto_的内置属性,用于指向创建它的构造函数的原型对象。
对象person1有一个_proto_属性,创建它的构造函数是Person,构造函数的原型对象是Person.prototype,所以
person1._proto_ = Person.prototype;
Person的原型对象为Person.prototype; Person.prototype.constructor = Person; person1._proto_ = Person.prototype; person1.constructor = Person;
五、检验对原型链的理解
1、person1_proto_是什么?
解:意思是实例对象person1的构造函数的原型对象,首先person1的构造函数是Person,然后Person的原型对象是Person.prototype。所以person1_proto
= Person.prototype。
2、Person_proto_是什么?
解:因为Person在创建时是通过function Person(){}的形式创建的,所以Person的构造函数是Function,而Function的构造函数是Function.prototype。所以Person_proto
= Function.prototype。
3、Person.prototype._proto_是什么?
解:在前面提过Person.prototype是一个普通对象,所以他的构造函数是Object,Object的原型对象是Object.prototype;
4、Object._proto_是什么?
解:Object和Person一样是函数对象,所以两者答案一样。
5、Object.prototype._proto_是什么?
解:这个比较特殊,结果为null,因为null位于原型链的顶端。
六、函数对象
所有函数对象,包括:Number、Boolean、String、Function、Object的_proto_都是Function.prototype。
Number.__proto__ === Function.prototype // true Number.constructor == Function //true Boolean.__proto__ === Function.prototype // true Boolean.constructor == Function //true String.__proto__ === Function.prototype // true String.constructor == Function //true Object.__proto__ === Function.prototype // true Object.constructor == Function // true Function.__proto__ === Function.prototype // true Function.constructor == Function //true Array.__proto__ === Function.prototype // true Array.constructor == Function //true RegExp.__proto__ === Function.prototype // true RegExp.constructor == Function //true Error.__proto__ === Function.prototype // true Error.constructor == Function //true Date.__proto__ === Function.prototype // true Date.constructor == Function //true
ECMAScript中内置构造器有12个,这里列举了8个构造器。剩下的如Global不可以访问,Arguments仅在函数调用时由JS引擎创建,Math、JSON是以对象形式存在的。他们的构造函数是Object,_proto_是Object.prototype。如下代码:
Math.__proto__ === Object.prototype // true Math.construrctor == Object // true JSON.__proto__ === Object.prototype // true JSON.construrctor == Object //true
所有的构造器都继承于Function.prototype,甚至包括根构造器Object和Function自身。
Function.prototype也是唯一一个类型为Function的原型对象。其他构造器的原型对象的类型都是Object。看如下代码:
console.log(typeof Function.prototype) // function console.log(typeof Object.prototype) // object console.log(typeof Number.prototype) // object console.log(typeof Boolean.prototype) // object console.log(typeof String.prototype) // object console.log(typeof Array.prototype) // object console.log(typeof RegExp.prototype) // object console.log(typeof Error.prototype) // object console.log(typeof Date.prototype) // object console.log(typeof Object.prototype) // object
这里可能有一个疑问,Function.prototype是一个Function,那么Function.prototype的构造函数应该是Function,Function.prototype._proto_岂不是Function.prototype,这样就进入一个死循环。其实ESMASript中Function.prototype._proto是Object.prototype,而Object.prototype._proto_则是原型链最顶端的null。
六、构造器的继承
在Object的原型对象里面有着如下图中的所有属性,
而当我们创建一个数组时:
var arr = new Array();
arr继承了Array.prototype的所有属性和方法,如下图:
但是却没有找到constructor,按照道理来说,每一个函数对象的原型对象都应该有constroctor才对。原因是,因为Array.prototype是一个对象,Array.prototype继承了Object.prototype的所有属性和方法,所以Array.prototype最终是拥有constructor属性的。
相关文章推荐
- 深入理解JavaScript 原型和原型链
- 深入理解JavaScript系列(5):强大的原型和原型链
- 深入理解JavaScript系列(5):强大的原型和原型链
- 进阶1.JavaScript深入之从原型到原型链
- 深入理解JavaScript系列(5):强大的原型和原型链
- 深入理解JavaScript系列(5):强大的原型和原型链
- 深入理解JavaScript系列(5):强大的原型和原型链
- 深入理解JavaScript系列(5):强大的原型和原型链
- 深入理解JavaScript系列(5):强大的原型和原型链
- 深入理解JavaScript系列(6) 强大的原型和原型链
- 深入理解JavaScript系列(5):强大的原型和原型链
- 深入理解JavaScript系列(6) 强大的原型和原型链
- 深入理解JavaScript系列 ----(5):强大的原型和原型链
- 深入理解JavaScript的原型和原型链
- 深入理解JavaScript系列(5):强大的原型和原型链
- 深入理解JavaScript系列(5):强大的原型和原型链
- <深入理解JavaScript>学习笔记(5)_强大的原型和原型链
- 深入理解JavaScript系列(5):强大的原型和原型链
- 深入理解JavaScript系列(5):强大的原型和原型链
- 深入理解JavaScript系列(5):强大的原型和原型链