众所周知,JavaScript中是没有传统类的概念的,js通过原型链的方式实现继承。原型是js学习中的一大重点知识,在ES6出来之前,因为js不像php、java一样拥有类的写法,所以继承方式也就不像php、java一样通过关键字extends实现子类继承父类的方式,但是js有它独特的实现继承的方式,这种方式有:prototype、原型冒充、复制继承。

1、prototype

  js中每个函数就是一个对象,每个对象都有自己的prototype属性,通过这个属性,可以指定某一类对象的原型

  1.  function Person(name,age,sex){
  2.     this.name = name || " ", //设置默认值,如果传入实参,this.name的值就等于实参的值,否则this.name的值默认为 " "
  3.     this.age = age || 24,
  4.     this.sex = "男" || sex,
  5.     this.say = function (){
  6.       console.log("我会说话");
  7.     },
  8.     this.smile = function(){
  9.       console.log("笑");
  10.     },
  11.     this.walk = function(){
  12.       console.log("走路");
  13.     }
  14.   };
  15.  
  16. function Monkey(){
  17. this.type = "monkey";
  18. };
  19. var oop = new Person();
  20. Monkey.prototype = oop;
  21. var oom = new Monkey();
  22. //执行oom.say()输出 我会说话
  23. oom.say();

oom对象并没有say()方法,为什么程序没有保存而且控制台还输出了 “我会说话”。因为oom对象的构造函数的prototype属性指向oop对象,表明由Monkey构造函数创建出来的一类对象,他们都具有共同的原型:oop对象。所以oom对象调用say()方法中,程序会默认先在oom对象中查找,如果没有找到这个属性,程序会沿着原型链往上寻找该属性。

需要注意的是,js中new  构造函数()这个过程发生了如下的操作:

a、创建空对象 { };

b、this指向空对象{ };

c、执行构造函数的函数体。

在过程c中,如果你熟悉js的为对象添加属性的方式(对象名 属性),你会发现,过程c其实就是给这个空对象添加属性和方法的过程。

构造函数名 。prototype = 对象 ,这个对象也可以是自定义的对象,在这个对象中定义了需要用到的方法和值。如下例子所示:

  1. function op(){
  2.   a = 3;
  3. };
  4.  
  5. var obj = {
  6.   para : 1,
  7.   say : function(){console.log("obj");}
  8. };
  9. //指定构造函数op的原型是obj对象;
  10. op.prototype = obj;
  11.  
  12. //由构造函数op创建的oop对象能够调用对象obj中的方法
  13. var oop = new op();
  14. oop.say();

2、原型冒充

  原型冒充的原理是通过call()与apply()函数改变当前对象的this的执行上下文。这话说的有点抽象,下面直接用例子解释:

 

  1.  //函数
  2.   function increase(a , b){
  3.     return a+b;
  4.   };
  5.  
  6.   function reduce(a , b){
  7.     return a-b;
  8.   }
  9.   increase . call(reduce,1,2); //输出3
  10.  
  11.   reduce . call(increase,1,2); //输出-1
  12.  
  13. 解释 :对象A . call(对象B , 参数1 , 参数2 , ......参数n)中执行了这样的操作:
  14.  
  15. a、修改对象Athis的指向,使其暂时指向对象B,参数1与参数2是传入对象B的实参。
  16.  
  17. b、执行调用call()方法的对象。
  18.  
  19. 所以increase . call(reduce,1,2); 这一句相当于increasethis指向reduce,然后执行increase(1,2),所以最终结果输出3
  20.  
  21. //对象
  22.  
  23. function person(name){
  24. this.name = name;
  25. this.say = function(){
  26. console.log(this.name);
  27. }
  28. };
  29. var op = new person("张三");
  30. op.say();
  31.  
  32. function lisi(name){
  33. this.name = name;
  34. };
  35. var ls = new lisi("李四");
  36. op.say.call(ls);//this指向ls :op.say(){ console.log(ls.name) },执行op.say()方法,输出 李四

op.say.call(ls)这句代码先是将say()函数体内的this指向ls,然后执行say()方法。op.say();这一步在正常情况下输出的结果应该是"张三",但是为什么却是“李四”了呢?原因是op.say.call(ls)这句代码将say()函数在程序解析到这句代码的位置时,this暂时指向对象ls,所以在op对象的say()体内的输出语句console.log(this.name)实际上是console.log(ls.name);

3、复制继承

  复制继承的原理是,将对象以参数的形式传递到构造函数中,在构造函数中通过对象属性的方式(Objname . propertyname或者Objname[propername])访问盖对象的属性值,将值赋予当前对象的属性。

  

  1. function Person(){
  2. this.name = "张三";
  3. this.age = 24;
  4. this.sex = "男"
  5. }
  6.  
  7. function children(per){
  8. this.name = per.name;
  9. this.age = per.age;
  10. this.sex = per.sex;
  11.  
  12. }
  13. var op = new Person();
  14. //向children构造函数中传入op对象,在children函数内完成值的复制
  15. var chi = new children(op);
  16. console.log(chi.age);

以上均是js原型继承的实现方式,在js这个海洋中,因为知识有限,所以博客还存在很多不足之处,希望更够跟大家多多交流学习。

谈谈我认识的js原型的更多相关文章

  1. JS原型链

    JS作为发展了多年了对象语言,支持继承,和完全面向对象语言不同的是,JS依赖原型链来实现对象的继承. 首先JS的对象分两大类,函数对象和普通对象,每个对象均内置__proto__属性,在不人为赋值__ ...

  2. 深入分析JS原型链以及为什么不能在原型链上使用对象

    在刚刚接触JS原型链的时候都会接触到一个熟悉的名词:prototype:如果你曾经深入过prototype,你会接触到另一个名词:__proto__(注意:两边各有两条下划线,不是一条).以下将会围绕 ...

  3. 【09-23】js原型继承学习笔记

    js原型继承学习笔记 function funcA(){ this.a="prototype a"; } var b=new funcA(); b.a="object a ...

  4. js原型

    1.js基本类型和对象类型 js的简单类型包括数字(其中NaN为数字类型).字符串(类似'A'为字符,js没字符类型).布尔值.null值和undefined值.其他所有的值都是对象.数字.字符串和布 ...

  5. js原型链与继承(初体验)

    js原型链与继承是js中的重点,所以我们通过以下三个例子来进行详细的讲解. 首先定义一个对象obj,该对象的原型为obj._proto_,我们可以用ES5中的getPrototypeOf这一方法来查询 ...

  6. JS 原型链图形详解

    JS原型链 这篇文章是「深入ECMA-262-3」系列的一个概览和摘要.每个部分都包含了对应章节的链接,所以你可以阅读它们以便对其有更深的理解. 对象 ECMAScript做为一个高度抽象的面向对象语 ...

  7. js原型解析

    我们都知道javascript因为具有了继承以及变量等等一系列的特性之后才被人们认为具有一门编程语言的资格,在后续的不断发展中,js在原生的基础上扩展了基于jquery等等的库,甚至衍生了像node. ...

  8. 深入理解JS原型链与继承

    我 觉得阅读精彩的文章是提升自己最快的方法,而且我发现人在不同阶段看待同样的东西都会有不同的收获,有一天你看到一本好书或者好的文章,请记得收藏起来, 隔断时间再去看看,我想应该会有很大的收获.其实今天 ...

  9. 学习zepto.js(原型方法)

    学习zepto.js(原型方法)[1] 转载 新的一周,新的开始,今天来学习一下zepto里边的原型方法,就是通过$.进行调用的方法,也是可以通过$.fn进行扩展的方法: $.camelCase(): ...

随机推荐

  1. vue3-组件中使用setup函数获取vuex中的数据的新方式

    传统方式 setup() { const store = useStore() //传统方式 const aName = computed(() => store.state.name) ret ...

  2. MATLAB绘制一幅中国地图

    今天博主跟大家讲一下如何用MATLAB制作一幅中国地图,那废话不多说,我们先看一下最终效果吧. mercator墨卡托圆柱投影地图 lambert兰伯特圆锥投影地图 一张中国地图大概包括以下要素: 中 ...

  3. 基于python 实现KNN 算法

    #!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/11/7 14:50 # @Author : gylhaut # @Site ...

  4. emu8086实现两位数加法运算

    题目说明:给出一个公式,例如 "35 + 28 = ",输出计算结果 一.准备材料 DOS功能调用表:https://blog.csdn.net/mybelief321/artic ...

  5. 【Vulnhub练习】Acid

    靶机信息 下载链接 https://download.vulnhub.com/acid/Acid.rar 靶机说明 Welcome to the world of Acid. Fairy tails ...

  6. 字节跳动社会招聘&内推-帮助你更快加入字节跳动

    字节跳动社会招聘&内推「[内推码]:4J8CA3W」 内推时间:一直有效 招聘对象:根据招聘要求而定 社招投递链接: https://job.toutiao.com/s/de5teaA 应届生 ...

  7. manjaro下使用scrcpy安卓设备投屏

    scrcpy 安卓版本要大于等于 5.0 安装scrcpy及安卓工具包 yay -S scrcpy-git android-tools 打开手机 开发者模式->USB调试,将手机通过数据线连接电 ...

  8. 保姆教程系列二、Nacos实现注册中心

    前言: 请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i 上篇我们介绍到  保姆教程系列一.Linux搭建Nacos 注册中心原理 一.环境准备 Java版本:1.8+   (Linux ce ...

  9. java反射 java动态代理和cglib动态代理的区别

    java反射      https://blog.csdn.net/f2764052703/article/details/89311013 java 动态代理   https://blog.csdn ...

  10. BeanFactory – BeanFactory 实现举例?

    Bean 工厂是工厂模式的一个实现,提供了控制反转功能,用来把应用的配置和依赖从正真的应用代码中分离. 最常用的BeanFactory 实现是XmlBeanFactory 类.