javascript中继承(一)-----原型链继承的个人理解
【寒暄】好久没有更新博客了,说来话长,因为我下定决心要从一个后台程序员转为Front End,其间走过了一段漫长而艰辛的时光,今天跟大家分享下自己对javascript中原型链继承的理解。
总的说来,js中的常用的继承方式可以分为两种,一种是原型链式继承,这也是本文要谈的重点;另外一种是借用构造函数继承,这方面的理解,我将在下次的博客中更新。好了,闲话不多说,进入正题。
一,关于原型
function Person(){}//这里我们声明一个函数Person,js中函数是对象,也是构造函数
console.log(Person.prototype)//打印一下Person对象的原型,会出现什么呢?如下图所示:
大家在图中看到了,Person对象的原型拥有一个constructor,它指向Person的构造函数,即Person本身,另外一个属性是__proto__属性,这个属性我会在后文中说明。
到这里,大家肯定会明白了,一个对象建立后,会产生一个局部的“小链式结构”,即Person对象拥有一个prototype属性,这个属性指向原型对象,在原型对象中又有一个构造器constructor,指向构造函数。用一张图来说明:
那么,原型对象的作用是什么呢?这个原型对象包含由特定类型的实例共享的属性和方法。大家要注意共享这两个字,用一段代码解释下
function Person(){
this.name="bob" //这是一个实例属性
}
Person.prototype.eat=function(){ //给对象的原型对象添加一个eat的方法,接下来,new的实例会共享这个方法
return "food";
}
var p1=new Person(); //这里究竟发生生了什么?
p1.eat()//->food
var p2=new Person();
p2.eat()//->food,所以只要是Person的对象,他们都会共享原型对象的方法,当然,p1.name也会共享Person的实例属性,因为p1是Person的一个实例
好了,到这里原型的概念我们已经讲完了,大家或许会疑问,上面的new一个Person实例的过程中究竟发生了什么呢?为什么这个实例能够访问到原型对象中的方法?其实,在这个过程过程中,p1实例拥有了一个指针,这个指针指向构造函数的原型对象。此时原型对象中的方法自然能够被实例所访问。用一张图来说明下:
这里,我们总结下构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象拥有一个指向构造函数的指针,而实例拥有一个指向原型对象的内部指针(这就是前面所提到的[[Prototype]],即__proto__,要注意的是这个__proto__属性在chrome浏览器中是可以看到的,而在大部分浏览器是隐藏的!)
二,关于原型链继承
好了,说了这么多终于到回到我们的主角了【原型链】,提出一个思考:如果我们让原型对象等于另外一个对象的实例,将会有一个什么样的结果呢?先看下面一段代码
function Person(){
this.name="bob";
}
Person.prototype.eat=function(){
return "food";
}
function Student(){}
Student.prototype=new Person();//将Person实例赋给Student的原型对象
var one=new Student();
one.name//bob
one.eat()//food,Student的实例能访问到Person对象的实例方法,也能访问到其原型属性中的方法
以上就是原型链继承的一种基本模式,那么我们怎么解释这样的原理呢?之前说过,对象的实例拥有一个指向原型对象的指针,那么student的原型对象拥有了Person对象实例后,自然也拥有一个指向Person原型对象的指针。此时,我们再new一个Student实例one时,one实例包含一个指向Student原型的指针,而Student.prototype拥有一个指向Person原型对象的指针,Person原型本身包含一个指向自身构造函数的指针。这样一来,就构成了实例与原型的链条。这就是所谓的原型链的概念!
用一张图描绘一下上面讲的情况:
大家要注意一下,这里的one对象的constructor现在指向谁呢?它并不指向Student,因为Student的原型指向另一个对象--Person的原型,而这个原型对象的constructor指向的是Person。
三,原型链方法的改写及注意的问题
function Person(){
this.name="bob" ;
}
Person.prototype.eat=function(){
return "food";
}
function Student(){}
//Student.prototype.eat=function(){
// return "food1";
//}
//注意如果更改原型语句的代码放在替换之前,那么下面one.eat()的结果将仍然是food
//,原因很简单,前面对prototype对象的修改,在后面的替换一句中被Person实例对象覆盖了
//,换句话说,就是现在的prototype实例中仍旧是以前的eat方法
Student.prototype=new Person();
Student.prototype.eat=function(){
return "food1";
}
var one=new Student();
console.log(one.eat());//food1
但是大家要注意一下一种情况,在通过原型链继承时,不能通过对象字面量个方式来更新原型对象
function Person(){
this.name="bob" ;
}
Person.prototype.eat=function(){
return "food";
}
function Student(){}
Student.prototype=new Person();
Student.prototype={
run:function(){
return "run";
}
};
var one=new Student();
console.log(one.eat());//Uncaught TypeError: undefined is not a function
function Person(){
this.name="bob" ;
}
Person.prototype.eat=function(){
return "food";
}
function Student(){}
Student.prototype=new Person();
Student.prototype.constructor=Student;//把Student原型对象中原本指向Person构造函数的对象强行指向到Student
var one=new Student();
console.log(one.eat());//food
从代码运行的情况来看,这个动作并没有切断原型链的继承,原因何在?
四,如何确定原型和实例关系
function Person(){
this.name="bob" ;
}
Person.prototype.eat=function(){
return "food";
}
function Student(){}
Student.prototype=new Person();
Student.prototype.constructor=Student;
var one=new Student();
var person=new Person();
console.log(one instanceof Student);//true
console.log(one instanceof Person);//true
console.log(person instanceof Person);//true
console.log(person instanceof Student);//false
最后一个出现了false,什么原因,instanceof的工作原理是什么呢?
function Person(){
this.name="bob" ;
}
Person.prototype.eat=function(){
return "food";
}
function Student(){}
Student.prototype=new Person();
var one=new Student();
var person=new Person();
console.log(Student.prototype.isPrototypeOf(one));//true
console.log(Person.prototype.isPrototypeOf(one));//true
console.log(Person.prototype.isPrototypeOf(person));//true
console.log(Student.prototype.isPrototypeOf(person));//false
五,总结
javascript中继承(一)-----原型链继承的个人理解的更多相关文章
- 一步步学习javascript基础篇(5):面向对象设计之对象继承(原型链继承)
上一篇介绍了对象创建的几种基本方式,今天我们看分析下对象的继承. 一.原型链继承 1.通过设置prototype指向“父类”的实例来实现继承. function Obj1() { this.name1 ...
- JavaScript 随笔2 面向对象 原型链 继承
第六章 面向对象的程序设计 1.创建对象的几种方式 A)工厂模式 function CreatObj(name,sex,age){ this.name=name; this.sex=sex; this ...
- Typescript中的类 Es5中的类和静态方法和继承(原型链继承、对象冒充继承、原型链+对象冒充组合继承)
<!doctype html> <html> <head> <meta charset="utf-8"> <meta name ...
- js继承之原型链继承
面向对象编程都会涉及到继承这个概念,JS中实现继承的方式主要是通过原型链的方法. 一.构造函数.原型与实例之间的关系 每创建一个函数,该函数就会自动带有一个 prototype 属性.该属性是个指针, ...
- 三张图搞懂JavaScript的原型对象与原型链 / js继承,各种继承的优缺点(原型链继承,组合继承,寄生组合继承)
摘自:https://www.cnblogs.com/shuiyi/p/5305435.html 对于新人来说,JavaScript的原型是一个很让人头疼的事情,一来prototype容易与__pro ...
- 一篇JavaScript技术栈带你了解继承和原型链
作者 | Jeskson 来源 | 达达前端小酒馆 1 在学习JavaScript中,我们知道它是一种灵活的语言,具有面向对象,函数式风格的编程模式,面向对象具有两点要记住,三大特性,六大原则. 那么 ...
- 深入浅出JavaScript之原型链&继承
Javascript语言的继承机制,它没有"子类"和"父类"的概念,也没有"类"(class)和"实例"(instanc ...
- JS中原型链继承
当我们通过构造函数A来实现一项功能的时候,而构造函数B中需要用到构造函数A中的属性或者方法,如果我们对B中的属性或者方法进行重写就会出现冗杂的代码,同时写出来也很是麻烦.而在js中每个函数都有个原型, ...
- JavaScript之继承(原型链)
JavaScript之继承(原型链) 我们知道继承是oo语言中不可缺少的一部分,对于JavaScript也是如此.一般的继承有两种方式:其一,接口继承,只继承方法的签名:其二,实现继承,继承实际的方法 ...
随机推荐
- php验证是否是md5编码的代码
php验证是否是md5编码的示例. 代码很简单,使用了正则表达式. function is_md5($password) { return preg_match("/^[a-z0-9 ...
- 通过messenger实现activity与service的相互通信
布局: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:to ...
- delphi 连接MYSQL 的方法
需要的控件:(view as form) 1.SQLConnection1: TSQLConnection ConnectionName = 'MYSQLCONNECTION' DriverName ...
- SQL Server 基础:Cast和Convert的区别
CAST 和 CONVERT 都可以将某种数据类型的表达式显式转换为另一种数据类型. 语法: CAST ( expression AS data_type ) CONVERT (data_type[( ...
- [FAQ]String(字串相連)與StringBuilder的差別、原理與優缺點?
原文位於 http://www.dotblogs.com.tw/mis2000lab/archive/2013/09/09/msdn_string_stringbuilder.aspx [FAQ]St ...
- C# 笛卡尔积
void Main() { string[] str1 = { "a", "b" }; " }; string[] str3 = { "一& ...
- Python脚本控制的WebDriver 常用操作 <四> 设置浏览器大小
下面将使用webdriver来控制浏览器窗口的大小 测试用例场景 设置浏览器窗口的大小有下面两个比较常见的用途: 在统一的浏览器大小下运行用例,可以比较容易的跟一些基于图像比对的工具进行结合,提升测试 ...
- CodeForces 569A 第八次比赛 C题
Description Little Lesha loves listening to music via his smartphone. But the smartphone doesn't hav ...
- qu
离骚 (3481人评分) 8.5 朝代:先秦 作者:屈原 原文: 帝高阳之苗裔兮,朕皇考曰伯庸.摄提贞于孟陬兮,惟庚寅吾以降.皇览揆余初度兮,肇锡余以嘉名:名余曰正则兮,字余曰灵均.纷吾既有此内美 ...
- iOS学习之视图控制器
一.自定义视图(label-textField组合视图) 1.自定义视图:系统标准UI之外,自己组合出的新的视图. 2.优点:iOS提供了很多UI组件,借助它们我们可以实现不同的功 ...