首页 > 技术文章 > H5前端技术文章 >

JavaScript系列-2-原型

更新时间:2019-04-12 | 阅读量(566)

>本文作者:钟昕灵,叩丁狼高级讲师。原创文章,转载请注明出处。 ## 原型对象释义 每一个构造函数都有一个与之相关联的对象,该对象称之为原型对象。 每个实例对象都能共享其原型对象上的属性和方法。 原型对象的作用主要用来实现属性的继承,让实例对象能共享原型对象的属性,减少内存分配。 所以,在上一节中,我们想在每个Person对象中共享同一个say方法,可以这样来实现。 ```javascript function Person(name, age) { this.name = name; this.age = age; } //在原型对象上添加say函数,实例对象共享该函数 Person.prototype.say = function(){ console.log("say hello"); }; var p = new Person("zs", 10, say); p.say(); var p2 = new Person("zs", 10, say); p2.say(); ``` 在原型对象上添加成员的方法: ​ 构造函数.prototype.成员名 = 成员值; 为Person原型对象添加say方法后,实现了在多个实例对象上共享该方法的功能。 获取原型对象的方法: ​ 构造函数.prototype ​ 实例对象.__ proto __ 在每个实例对象上都有一个__ proto __的属性,也是用来获取该对象的原型对象。 Person.prototype == p.__ proto __;//true 下图详细说明了各对象之间的关系: ![image.png](https://upload-images.jianshu.io/upload_images/11387429-9a5de47d348130c8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ## 面向对象中的核心概念 **构造函数:**Person,和new关键字一起创建对象 **构造函数的原型对象:**Person.prototype, **原型对象:**和创建实例对象的构造函数相互关联的对象 **实例对象:**由构造器创建出来的对象称之为实例对象 **实例化:**由构造器创建实例对象的过程称之为实例化 **对象的成员:**属性+方法 **实例成员:**实例对象上的属性和方法,name,age,只能当前实例对象才能访问 **原型成员:**原型对象上的属性和方法,say(),使用该原型对象对应构造器创建出来的所有实例对象都能访问 **静态成员:**直接添加在构造函数上的属性和方法,只能使用构造函数才能访问 ## __ proto __属性介绍 该属性是在ES6之后才纳入规范,在这之前,只有部分浏览器实现。 该属性可以获取指定实例对象的原型对象,p.__ proto __,和Person.prototype获取的一样 我们也可以使用Object构造器上的getPrototypeOf(实例对象)方法获取指定实例对象的原型对象 以上提到的三种获取原型对象的方法所得到的结果是一样的。即: Object.getPrototypeOf(p) == Person.prototype == p.__ proto __ ## 扩展内置对象 内置对象是JS中事先定义好的对象,可以直接拿来使用的对象,在这类对象中已经封装好了一堆的方法和属性,方便开发者完成基本的功能。 但是在实际开发中,这些属性或者方法不一定能够满足我们的需求,此时就需要对这些内置对象做功能扩展。 需求:为数组对象添加一个获取元素个数的方法 ```js var arr1 = [1, 2, 3]; var arr2 = ["A", "B", "C","D"]; arr1.getLength = function () { return this.length; } console.log(arr1.getLength()); ``` 上面为数组arr1添加了一个getLength()方法获取其元素个数,那么此时的arr2对象上有这个方法吗?相信大家心里都有答案。如果想要arr2拥有同样的功能,也需要同样的操作。 所以这种方式不可取,如果100个数组都想都需要这样的功能,操作起来就比较复杂了。 根据前面学过的知识点,我们完全可以使用原型来解决这个问题。 ```js var arr1 = [1, 2, 3]; var arr2 = ["A", "B", "C","D"]; Array.prototype.getLength = function () { return this.length; } console.log(arr1.getLength());// 3 console.log(arr2.getLength());// 4 ``` 我们直接在Array的原型对象上添加getLength()方法,之后创建的所有的数组对象都拥有了该方法,搞定! 这种方式能够解决我们的问题,但是还是存在问题的: 1. 在多人开发的环境中,如果使用这种方式对内置对象做扩展,可能会对其他开发人员造成影响 2. 如果在原型对象上添加了过多的成员,会降低对象成员的搜索效率。 ## 安全的扩展内置对象 上面扩展内置对象的方法存在一定的问题,问题的关键其实在于我们是直接在内置对象的原型上进行拓展的,这样导致对其他使用该对象的开发人员造成影响。 所以,我们的解决思路就是,自定义一个对象,让该对象继承需要扩展的内置对象,然后只需要对自定的对象进行操作即可。 ```js function MyArray() { } //让MyArray的原型指向Array对象 //即继承Array中的所有成员 MyArray.prototype= new Array(); MyArray.prototype.getLength=function () { return this.length; } var arr1 = new MyArray(); arr1.push("A","B","C","D","E");//内置对象的初始方法 console.log(arr1.getLength());//扩展之后的方法 ``` 接下来,如果想要对数组做扩展,我们只需要操作MyArray即可,而不需要直接操作Array,如此,就不会对其他使用Array的开发人员操作影响了。看图理解: ![image.png](https://upload-images.jianshu.io/upload_images/11387429-2658aad8d484a3aa.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ## 原型链的结构图 每个实例对象都是由构造函数创建出来的 每一个构造函数都有默认关联的原型对象 原型对象本身也是对象,所以它也有自己的构造函数 原型对象的构造函数也有默认关联的原型对象 以上就构成了一种链式访问结构,称之为原型链 下面画出了Person对象和Array对象的原型链: ![image.png](https://upload-images.jianshu.io/upload_images/11387429-b25b8b13eff6b399.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
叩丁狼学员采访 叩丁狼学员采访
叩丁狼头条 叩丁狼头条
叩丁狼在线课程 叩丁狼在线课程