JavaScript是一种动态语言,你可以随时给对象添加属性,如下functionStudent(){this.name='LeBronJames';this.gender='Male';}varstudObj1=newStudent();studObj1.age=15;alert(studObj1.age);//15varstudObj2=newStudent();alert(studObj2.age);//undefined如上实例,年龄属性附加到studObj1实例。但是,studObj2实例没有此属性,因为age属性仅在studObj1实例上定义。那么,如果后面要添加一个属性,并且可以被所有实例共享,怎么办呢??答案是今天的主角Prototype.Prototype是一个对象,它默认与JavaScript中的任何函数或对象相关,但唯一的区别是函数的原型属性是可访问和修改的,而函数的原型属性是对象不可见。默认情况下,任何函数都包含一个Prototype对象,如下图所示:原型对象是一种特殊类型的可枚举对象,可以向其添加额外的属性,这些属性将在其构造函数的所有实例之间共享.我本人是一个从事多年开发的老web前端程序员。目前正在辞职做自己的web前端私人定制课程。今年年初,我花了一个月的时间整理了一个最适合2019年学习的web前端学习干货,各种框架整理出来送给每一位前端小伙伴。因此,利用上例中的函数原型,添加属性,使其可以被所有对象访问,如下:functionStudent(){this.name='LeBronJames';this.gender='M';}Student.prototype.age=15;varstudObj1=newStudent();alert(studObj1.age);//15varstudObj2=newStudent();alert(studObj2.age);//15使用字面量或者通过new关键字和构造函数创建的每个对象包含一个__proto__属性,指向创建该对象的函数的原型对象。你可以在Google和Firefox开发者调试工具中查看这个属性(__proto__),根据下面的例子:console.log(Student.prototype);//objectconsole.log(studObj.prototype);//undefinedconsole.log(studObj.__proto__);//objectconsole.log(typeofStudent.prototype);//objectconsole.log(typeofstudObj.__proto__);//objectconsole.log(Student.prototype===studObj.__proto__);//如上例所示,函数通过[[函数名]].prototype访问原型对象。但是,对象(实例)并没有暴露原型属性,而是使用__proto__来访问它。前面提到的Object对象的原型,原型对象在对象中是不可见的。使用Object.getPrototypeOf(obj)方法访问实例的原型对象。(这也是推荐的方式,__proto__不是标准属性,IE11以下其他浏览器没有实现)。functionStudent(){this.name='LeBronJames';this.gender='M';}varstudObj=newStudent();Student.prototype.sayHi=function(){alert("Hi");};varstudObj1=newStudent();varproto=Object.getPrototypeOf(studObj1);//returnsStudent'sprototypeobjectalert(proto.constructor);//returnsStudentfunctionObject原型对象包含以下属性和方法属性说明构造函数返回创建实例的构造函数__proto__指向创建实例的构造函数的原型对象。方法说明hasOwnProperty()返回布尔值表示对象是否包含指定属性作为对象的直接属性,而不是通过原型链继承isPrototypeOf()返回布尔值表示指定对象是否在原型链中调用此方法的对象。propertyIsEnumerable()返回一个布尔值,指示指定的属性是否可枚举。toLocaleString()返回本地格式的字符串。toString()以字符串形式返回一个对象。valueOf()返回指定对象的原始值。Chrome和Firefox将对象的原型表示为__proto__,而内部引用是[[Prototype]]。IE不支持,只有IE11支持。修改原型如上所述,每个对象都可以链接到函数的原型对象。如果更改函数的原型,则只有新对象会链接到更改后的原型。所有其他现有对象仍链接到旧函数原型。以下示例演示了这种情况:functionStudent(){this.name='LeBronJames';this.gender='M';}Student.prototype.age=15;varstudObj1=newStudent();alert('studObj1.age='+studObj1.age);//15varstudObj2=newStudent();alert('studObj2.age='+studObj2.age);//15Student.prototype={age:20};varstudObj3=newStudent();alert('studObj3.age='+studObj3.age);//20alert('studObj1.age='+studObj1.age);//15alert('studObj2.age='+studObj2.age);//15使用原型Theprototype对象被JavaScript引擎用来做两件事:查找对象的属性和方法,在JavaScript函数中实现继承Student(){this.name='LeBronJames';this.gender='M';}Student.prototype.sayHi=function(){alert("Hi");};varstudObj=newStudent();studObj.toString();在上面的例子中,toString()方法没有在Student中定义,所以它是如何找到toString()的,在哪里找到的?在这里,原型出现了。首先,JavaScript引擎检查studObj是否存在toString方法?。如果没有找到,那么它使用studObj的__proto__链接指向Student函数的原型对象。如果仍然找不到,则继续检查Object函数的原型对象,因为在JavaScript中所有对象都是从Object派生的,然后找到toString()方法。因此,它在Object函数的原型对象中找到了toString()方法,我们就可以调用studObj.toString()了。搜索方法,如下图所示,是原型及其应用的基础知识。
