prototype和原型链查找:
任何函数都有 prototype属性, prototype是英语“原型”的意思。prototype属性值是个对象,它默认拥有constructor属性指回函数。
举个栗子:

        function sum(a,b){return a+b;}console.log(sum.prototype); // {constructor: ƒ}console.log(typeof sum.prototype); // objectconsole.log(sum.prototype.constructor == sum); // true

普通函数来说的prototype是没有任何用处的,但构造函数的prototype属性非常有用。
注意:构造函数的prototype属性是它的实例的原型
见图:

这里面的 _proto_不是W3C的标准属性,而是谷歌浏览器为了学习者学习而创造出现的属性。虽然 _proto_不是标准属性,但原型这条线是在所有浏览器中都存在的,只不过在谷歌浏览器中可以访问到这条线的。
举个栗子:

        function People(name,age,sex) {this.name = name;this.age = age;this.sex = sex;}
// 实例化:var xiaoming = new People('xiaoming',18,'male');
// 测试:console.log(xiaoming.__proto__ == People.prototype); // true

原型链查找:
Javascript规定:实例可以打点访问它的原型的属性和方法,这被称为“原型链查找”
举个栗子:

    function People(name,age,sex) {this.name = name;this.age = age;this.sex = sex;}// 往原型上添加nationality属性:People.prototype.nationality = '中国';var xiaoming = new People('xiaoming',18,'male');console.log(xiaoming.nationality); // 中国console.log(xiaoming);

在这里显示中国是没有任何问题的因为:

在原型链上是可以查找到的。
可以看这副图:


要打印的是xiaoming.nationality,因为xiaoming身上没有nationality属性,但People.prototype里面有nationality这个属性,所以就会通过_proto_这个链去查找nationality,所以打印出来结果就是中国。

说到这个给一个题目:

问:实例化一个对象Tom,在没有给Tom添加nationality属性时问console.log(Tom.nationality)的值和给Tom添加Tom.nationality = '美国';console.log(Tom.nationality)的值?
大家想想应该都能得出结果,在没有添加时,Tom没有nationality这个属性,因此就会往原型上找,所以打印出来的结果是中国,但如果一添加Tom.nationality,那么在打印Tom.nationality时就不需要往原型上找了(自身就有),所以打印出来的结果是美国。

    function People(name,age,sex) {this.name = name;this.age = age;this.sex = sex;}// 往原型链上设置nationality属性:People.prototype.nationality = '中国';// 实例化Tom:var Tom = new People('Tom',20,'男');Tom.nationality = '美国';console.log(Tom.nationality); // 美国

这种情况也叫原型链的遮蔽效应。
hasOwnProperty:
hasOwnProperty方法可以检查对象是否真正“自己拥有”某种属性或者方法。
举例:

    function People(name,age,sex) {this.name = name;this.age = age;this.sex = sex;}// 往原型链上设置nationality属性:People.prototype.nationality = '中国';// 实例化xiaoming:var xiaoming = new People('xiaoming',18,'male');console.log(xiaoming.hasOwnProperty('name')); // trueconsole.log(xiaoming.hasOwnProperty('age')); // trueconsole.log(xiaoming.hasOwnProperty('sex')); // true
// xiaoming不是自己用于nationality属性,所以结果是falseconsole.log(xiaoming.hasOwnProperty('nationality')); // false

in:
in运算符只能检查某个属性或方法是否可以被对象访问,不能检查是否是自己的属性或方法。
举例:

    function People(name,age,sex) {this.name = name;this.age = age;this.sex = sex;}// 往原型链上设置nationality属性:People.prototype.nationality = '中国';// 实例化xiaoming:var xiaoming = new People('xiaoming',18,'male');console.log('name' in xiaoming); // trueconsole.log('age' in xiaoming); // trueconsole.log('sex' in xiaoming); //trueconsole.log('nationality' in xiaoming); // true

在构造函数里字面量添加方法:
举例:

        function People(name,age,sex) {this.sayHello = function() {}}var xiaoming = new People();var xiaohong = new People();var xiaogang = new People();console.log(xiaoming.sayHello == xiaohong.sayHello); // false

在实例化的时候它们不是同一个引用,指向不同的堆内存。

缺点: 把方法直接添加到实例身上的缺点:每个实例和每个实例的方法函数都是内存中的不同函数,会造成内存的浪费。
解决方法: 将方法写到prototype上面。
图片演示:

在People.prototype上添加方法时,在实例化时都是顺着_proto_这个原型链往People.protype里面找,因为People.prototype是同一个引用,所以可以解决内存的浪费问题。

代码:

        function People(name,age,sex) {this.name = name;this.age = age;this.sex = sex;}// 把方法写到原型上,工整,减少内存占用People.prototype.sayHello = function() {console.log('我是' + this.name + ',我' + this.age + '岁了');}People.prototype.grown = function() {this.age++;}var xiaoming = new People('小明',20,'男');var xiaohong = new People('小红',10,'女');console.log(xiaoming.sayHelllo() == xiaohong.sayHello()); // truexiaoming.sayHello(); // 我是小明,我20岁了xiaohong.sayHello(); // 我是小红,我10岁了xiaoming.grown();xiaoming.grown();xiaoming.grown();xiaoming.sayHello(); //  我是小明,我23岁了xiaohong.sayHello(); // 我是小红,我10岁了

原型链的终点:

大家先看这张图:

在这张图片中Peopel.prototype相当于Object new出来的,所以People可以通过_proto_原型链查找到原型Object.prototype,可以通过console.log(xiaoming.__proto__.__proto__ == Object.prototype);进行验证,还有一点这里也可以解释了:上面我们讲过hasOwnProperty()toString()方法,知道xioaming可以打点调用这两个方法,为什么可以调用?这里就得到了答案,因为hasOwnProperty()toString()方法是原型链终点Object.prototype的方法,所以xiaoming可以通过原型链查找的方式去找到hasOwnProperty()toString()方法,因此可以打点调用,还有一点就是Object.prototype是原型链的终点,这点可以通过代码console.log(Object.prototype.__proto__);为null进行解释。

具体见下面代码:

        function People(name,age) {this.name = name;this.age = age;}var xiaoming = new People('小明',30);console.log(xiaoming.__proto__.__proto__ == Object.prototype); // trueconsole.log(Object.prototype.__proto__); // nullconsole.log(xiaoming.toString()); // [object Object]

这里还有个数组的原型链:

任何数组都是Array实例化的表现(Array new 出来的),在数组的原型链Array.prototype上有push() pop() slice()等方法,所以任何数组都可以打点调用这些方法,通过这点我们就能知道为什么数组可以调用那些方法了,还有一点就是数组的原型链终点也是Object.prototype,所以数组也可以调用hasOwnProperty()toString()方法的。

下面见代码演示:

        var arr = [44,55,33,66];
// 等价于 var arr = new Array(44,55,33,66);console.log(arr.__proto__ == Array.prototype); // trueconsole.log(arr.__proto__.__proto__ == Object.prototype); // trueconsole.log(Array.prototype.hasOwnProperty('push')); // trueconsole.log(Array.prototype.hasOwnProperty('pop')); // true

继承(面试题——手写继承):

1、实现继承的关键在于:子类必须拥有父类的全部属性和方法,同时子类还应该能定义自己特有的属性和方法。
2、使用Javascript特有的原型链特性来实现继承,是普遍的做法。
3、在今后学习ES6时会学习新的实现继承的方法。

见图:

讲解:先定义一个父类People,在父类身上添加方法sayHello(),sleep(),接着定义一个子类Student,然后将子类Student的原型Student.prototype指向父类People new 的实例,然后在子类的原型上(Student.prototype)添加方法study() exam()等,然后再实例化子类var hanmeimei = new Student(),然后hanmeimei就可以通过打点的方法调用各种方法(父类 子类均可以)。其中非常关键的一步就是:将子类Student的原型Student.prototype指向父类People new 的实例Student.prototype = new People();

见代码:

 // 父类:function People(name,age,sex) {this.name = name;this.age = age;this.sex = sex;}People.prototype.sayHello = function() {console.log('你好我是'+this.name+',我今年'+this.age+'岁了');}People.prototype.sleep = function() {console.log(this.name + '开始睡觉了 zzzzz');}// 子类 学生function Student(name,age,sex,scholl,studentNumber) {this.name = name;this.age = age;this.sex = sex;this.scholl = scholl;this.studentNumber = studentNumber;}// 关键语句,实现继承: 要写在子类添加方法之前Student.prototype = new People();Student.prototype.study = function() {console.log(this.name + '正在学习!');}Student.prototype.exam = function() {console.log(this.name + '正在考试!加油!');}// 实例化:var hanmeimei = new Student('韩梅梅',20,'女','爱大学','31299999');hanmeimei.study(); // 韩梅梅正在学习!hanmeimei.sayHello(); // 你好我是韩梅梅,我今年20岁了hanmeimei.exam(); // 韩梅梅正在考试!加油

拓展继承——手写父类的方法:

代码:

        function People(name,age,sex) {this.name = name;this.age = age;this.sex = sex;}People.prototype.sayHello = function() {console.log('你好我是'+this.name+',我今年'+this.age+'岁了');}People.prototype.sleep = function() {console.log(this.name + '开始睡觉了 zzzzz');}// 子类 学生function Student(name,age,sex,scholl,studentNumber) {this.name = name;this.age = age;this.sex = sex;this.scholl = scholl;this.studentNumber = studentNumber;}// 关键语句,实现继承:Student.prototype = new People();Student.prototype.study = function() {console.log(this.name + '正在学习!');}Student.prototype.exam = function() {console.log(this.name + '正在考试!加油!');}
///// 重写、复写(overwrite)父类的sayHello方法:Student.prototype.sayHello = function() {console.log('敬礼!我是' + this.name);}
//// 实例化:var hanmeimei = new Student('韩梅梅',20,'女','爱大学','31299999');hanmeimei.study(); // 韩梅梅正在学习!hanmeimei.sayHello(); // 敬礼!我是韩梅梅hanmeimei.exam(); // 韩梅梅正在考试!加油!

prototype全解全析相关推荐

  1. js原型、原型链、作用链、闭包全解

    https://www.2cto.com/kf/201711/698876.html [对象.变量] 一个对象就是一个类,可以理解为一个物体的标准化定义.它不是一个具体的实物,只是一个标准.而通过对象 ...

  2. js系列教程4-函数、函数参数全解

    全栈工程师开发手册 (作者:栾鹏) 快捷链接: js系列教程1-数组操作全解 js系列教程2-对象和属性全解 js系列教程3-字符串和正则全解 js系列教程4-函数与参数全解 js系列教程5-容器和算 ...

  3. js系列教程2-对象、对象属性全解

    全栈工程师开发手册 (作者:栾鹏) 快捷链接: js系列教程1-数组操作全解 js系列教程2-对象和属性全解 js系列教程3-字符串和正则全解 js系列教程4-函数与参数全解 js系列教程5-容器和算 ...

  4. js系列教程1-数组操作全解

    全栈工程师开发手册 (作者:栾鹏) 快捷链接: js系列教程1-数组操作全解 js系列教程2-对象和属性全解 js系列教程3-字符串和正则全解 js系列教程4-函数与参数全解 js系列教程5-容器和算 ...

  5. 百度地图历险记之LuShu路书全解

    百度地图历险记之LuShu路书全解 项目简介: 接了个双创项目的前端开发的活,主要用地图来展示一些信息,比如时间地点事件什么的.使用了Antd+react解决方案. 欢迎点个star支持下:思源siy ...

  6. 【HTML5】 Audio/Video全解(集合贴)

    [HTML5] Audio/Video全解(集合贴) 2015-03-17  chenh_doc 目录[-] 一.标签解读 二.Media对象方法和属性 三.Media JS事件 四.浏览器对音视频格 ...

  7. 一般将来时语法课教案_「英语语法」一般过去时用法技巧全解

    大家好,我是教课蚪英语的张老师,今天我们来学习英语语法100讲的第一课,一般过去时! 一.首先我们了解一下什么是一般过去时? 英语语法 1. 概念: 描述过去的状态或过去的动作. 在英语中,非现在的以 ...

  8. atca背板_ATCA介绍全解.ppt

    ATCA介绍全解 ATCA - 概述Advanced Telecommunications Computing Architecture 高性能计算机和网络通信设备的要求: 1) 足够强的数据处理能力 ...

  9. 生成对抗网络gan原理_中国首个“芯片大学”即将落地;生成对抗网络(GAN)的数学原理全解...

    开发者社区技术周刊又和大家见面了,萌妹子主播为您带来第三期"开发者技术联播".让我们一起听听,过去一周有哪些值得我们开发者关注的重要新闻吧. 中国首个芯片大学,南京集成电路大学即将 ...

最新文章

  1. 如果有电脑——计算机达人成长之路(36)
  2. 598. Range Addition II(Python)
  3. seo vue 动态路由_VUE项目SEO问题的解决
  4. java保存的时候保存多张表,表驱动,如何在表中存储一个方法
  5. E. 2-3-4 Tree
  6. C/C++(C++返回对象与应用区别,类成员的存储)
  7. Scrapy爬取hupu论坛标题统计数量并生成wordcloud
  8. java中equals重写_Java 中equals和toString()方法重写
  9. 几个简单的小功能,能提高微信群活跃度?
  10. 做SEO优化第九步:如何设置页面内容优化
  11. Python Turtle绘图基础(一)——Turtle简介、绘图窗体与绘图区域
  12. RabbitMQ之Channel
  13. 化合物相似性搜索_分子相似性的应用
  14. (六十二)基于logistic回归的信用评级和分类模型评估
  15. 计算机训练大纲,[工学]计算机技能训练大纲.doc
  16. airtest获取当前设备序列号,并连接
  17. 软件兼容性与软件兼容性测试
  18. 无聊,几行python代码写一个聊天机器人陪你聊天
  19. visio中画电路的节点
  20. 物联网无线传输模块 无线通信DTU

热门文章

  1. You have installed a lot of useless repos and Yum is not working properly becaus
  2. STC8H8K64U 的 USB 功能测试(未成功)
  3. Windows远程桌面连接不上问题
  4. Hive - ORC 文件存储格式详细解析
  5. 基于STM32,TB6612,TCRT5000的简易红外循迹小车
  6. MMLAB学习-Gard-CAM可视化方法
  7. 一款免费的网络流量实时监控软件
  8. java编写的生日礼物,感恩送书第1期:2019年快来了,感谢给位网友,送《Spring 5开发大全》...
  9. 游戏二次元场景插画教程,常见的6种构图方法分享
  10. 白鲸开源代立冬:一年5个孵化项目来自于中国,佛系Apache如何帮助中国开源立足全球?