javaScript-原型、继承-01
为什么会有原型这个概念;
1、优雅的创建对象;
2、继承;
先看js 之前创建对象的方式存在的问题;
创建对象方式
1、字面量
var obj={name:"join",age:18}
var obj1={name:"Tom",age:88}
当我们需要创建多个属性只有值不一样的对象时,这种方式就悲剧来了,会造成大量的冗余代码,最重要的是代码不能复用;
2、工厂模式
这种工厂模式并不是设计模式中的工厂方法,代码如下:
function createObj(name, age) {
var o = new Object();
o.name = name;
o.age = age;
o.sayHello= function() {
alert("Hello Word!");
}
return o;
}
var obj = createBlog("Tom", "88");
这种方式好多了,但是也存在一个问题,就是没办法知道一个对象是什么类型;console.log(typeof obj);//object
3、构造函数模式
function Person(name,age,job){ this.name=name; this.age=age; this.job=job; this.sayNmae=function(){ alert(this.name); }}var persong1=new Person("Join",18,"农民");var persong2=new Person("Join",18,"地主");
构造函数模式看起来oop(面向对象)多了,上面两种模式存在的问题在构造模式中都不存在了(创建对象的代码可以复用、对象类型可以识别)看起来世界挺美好,遗憾的是
这种还是存在一个问题;
1、每一个方法都要在每个实例上重新创建一次(问题不大);
2、从上面例子可以看出每个person 实例都包含一个不同的function 实例;不要忘了ECMAScript中的函数也是对象,所以上面的代码与下面的代码等价(主要会造成不同的作用域和解析问题)
function Person(name,age,job){
this.name=name;
this.age=age;
this.job=job;
this.sayNmae=new function(){
alert(this.name);
}
}
alert(person1.sayNmae==person2.sayNmae)// false 当然这个问题也是能解决的,就是把方法移到外面,让他成为全局的函数,但是这样一来该函数就只能由widows对象调用了,而且如果存在多个方法,就会存在多个全局函数,那我们自定义的的引用类型就丝毫没有封装可言了。好在这些问题都可言通过原型模式来解决;说了一大堆废话进入正题:原型,他是一个对象;
function特征
在js中一切都是对象,当我们写function 时js 就会同时创建它的prototype对象(原型对象),这个对象包含一个属性prototype(原型),这个属性是一个指针,该指针指向原型对象,
该对象的作用是特定类型(该类型实例的对象)的所有实例共享属性和方法;
function Person(name,age,job){
this.name=name; this.age=age; this.job=job;}Person.prototype.sayNmae=function(){ alert(this.name);}var persong1=new Person("Join",18,"农民");var persong2=new Person("Join",18,"地主");
alert(persong1.sayNmae==persong2.sayNmae)// true
Prototype对象
在默认情况下所有原型对象都会自动获得一个属性Constructor(构造函数属性)这个属性包含一个指向prototype属性所在的函数指针;
实例之New 操作符
创建一个实例通常会经历以下4步:
1、创建一个新的对象;
2、将构造函数的作用域赋给新对象(this指针指向这个新的对象);
3、执行构造函数中的代码(还会将该对象的__proto__指向了函数的prototype对象);
4、返回该对象;
需要注意的地方是当调用构造函数创建一个新对象后,该对象内部将包含一个指正(内部属性 _proto_),指向构造函数的原型对象(prototype 对象),该属性在ES6中貌似规范化了;
实例、构造函数、原型对象关系
创建的每个实例都会有一个内部属性_proto_ 指向构造函数的原型对象;
构造函数存在prototype 属性指向该函数的原型对象;
上面person代码如图:

图画的不好下次试试思维导图这个工具;
注意实例只跟原型对象有关系;
查找原理
当代码读取某个对象的属性或者方法时都会执行一次搜索,首先从从对象本身开始,如果存在则返回给定的属性名或者方法名,不存在继续搜索指针(_proto_)指向的原型对象,如上面的代码 persong1.sayNmae。首先解析器会问:"对象实例person1有sayName吗?",答:没有,然后继续搜索,问person1的原型有"sayName 吗?",答:有,读取原型对象中的函数;这就是多个实例共享原型中属性、方法的基本原理;
由此可知当实例中与原型中存在相同的属性名时会读取实例的属性名,但是他们之间不存在引用问题,即你设置了实例的属性为null,并不会影响到原型中的属性,他们终究是属于不同的对象;
更简单的原型语法
当我们要添加多个方法时,没必要每次都写类似这样的代码 Person.Prototype.XXX=function(){//doing something}
Person.Prototype={
constructor:Person,//注意这里要重写
sayAge:function(){ alert(this.age);},
sayJob:function(){ alert(this.job);}
}
这里为什么要重写constructor呢,很简单每创建一个函数,就会同时创建它的prototype对象(原型对象),这个对象也会获得constructor属性,
而上面我们重写了默认的prototype对象,因此constructor这时并没有指向Person,而是指向新object构造函数,所以这里要重写constructor让他指向Person;
原型动态性
原型是对象,对象是引用类型,所以当在原型中干了些什么事情,都能立即在实例对象上反应出来;
原生对象的模型
JS 原生的引用类型,都是采用这种模式创建的。如 在Array.prototype.sort(),可以找到sort()方法。
原型模式的问题
当我们把引用类型属性添加到原型对象时,会造成数据共享的问题,如 在person 中把一个数组放到原型对象中,此时所有的对象都会共享这个数组:
friedns:["tom","Join","Elie"];
当我们其中一个实例对这个对象进行push("Tem");
所有的实例都可以访问到"Tem";
组合使用构造函数与原型模式
基于上面数据共享的问题,解决方案通常是:属性写在构造函数中,方法写在原型中,这样每个实例都会有自己属性,同时又共享着方法的引用,这样既能最大限度的节省了内存;
总结
1、创建function 就会同时创建它的prototype对象(原型对象),function也是对象其实在原型对象中也存在一个默认的_proto_ 指向函数的原型对象(Function.prototype);
2、JS 每个对象中都存在_proto_,函数对象才存在prototype 属性,所以会看到一些博客说JS 对象分为两种:一种是Object(自定义),一种是function;
3、实例话对象就会把function中的prototype属性值赋给对象实例的_proto_;
4、原型是一个对象,我们可以重写该对象;
本人JS新手有误之处还请谅解,顺便指出错误,让我们这些新手有进步!
javaScript-原型、继承-01的更多相关文章
- 再谈javascript原型继承
Javascript原型继承是一个被说烂掉了的话题,但是自己对于这个问题一直没有彻底理解,今天花了点时间又看了一遍<Javascript模式>中关于原型实现继承的几种方法,下面来一一说明下 ...
- 彻底理解Javascript原型继承
彻底理解Javascript原型继承 之前写过一篇Javascript继承主题的文章,这篇文章作为一篇读书笔记,分析的不够深入. 本文试图进一步思考,争取彻底理解Javascript继承原理 实例成员 ...
- [转]Javascript原型继承
真正意义上来说Javascript并不是一门面向对象的语言,没有提供传统的继承方式,但是它提供了一种原型继承的方式,利用自身提供的原型属性来实现继承.Javascript原型继承是一个被说烂掉了的话题 ...
- JavaScript原型继承工作原理
原型继承的定义 当你阅读关于JS原型继承的解释时,你时常会看到以下这段文字: 当查找一个对象的属性时,JavaScript 会向上遍历原型链,直到找到给定名称的属性为止.——出自JavaScript秘 ...
- 【读书笔记】读《编写高质量代码—Web前端开发修炼之道》 - JavaScript原型继承与面向对象
JavaScript是基于原型的语言,通过new实例化出来的对象,其属性和行为来自于两部分,一部分来自于构造函数,另一部分是来自于原型.构造函数中定义的属性和行为的优先级比原型中定义的属性和优先级高, ...
- JavaScript 原型继承开端
1.原型继承本质 就javascript对象系统的实现来讲,对象并没有原型,而构造器有原型(构造器.prototype指向其原型).对象只有构造自某个原型的说法,并没有持有某个原型的说法. ...
- 浅析Javascript原型继承(转)
引自: http://blog.csdn.net/kittyjie/article/details/4380918 原作者解释的浅显易懂,非常不错的JavaScript prototype总结 JS没 ...
- Javascript原型继承容易忽略的错误
编写Javascript的开发者都知道,JS虽然没有类(ES6添加了class语法),但是可以模拟出OOP语言的类和面向对象的概念,比如我们都知道的一句话,Javascript中处处是对象,而面向对象 ...
- javascript原型继承圣杯模式
javascript纯面向对象开发需要使用到的一个模式,来对对象之间原型继承做中间层代理避免重复继承与代码杂乱 <!DOCTYPE html> <html lang="en ...
- javascript原型继承
在传统的基于Class的语言如Java.C++中,继承的本质是扩展一个已有的Class,并生成新的Subclass. 由于这类语言严格区分类和实例,继承实际上是类型的扩展.但是,JavaScript由 ...
随机推荐
- Android 高仿微信 获取最近刚刚拍照的缩略图 功能实现
原理其实挺简单的,android 中文件 修改 增加 删除等等 都会在数据库里的某个表里记录下来,你需要的时候 只要迅速的去查找这个表里的值 即可得到你想要的所有信息. 实际上 如果真正理解这个表结构 ...
- pthread_attr_t 线程属性(一)
1. 线程属性: 使用pthread_attr_t类型表示,我们需要对此结构体进行初始化, 初始化后使用,使用后还要进行去除初始化! ...
- [Everyday Mathematics]20150226
设 $z\in\bbC$ 适合 $|z+1|>2$. 试证: $$\bex |z^3+1|>1. \eex$$
- winform 防止多開
場景: 當我們的電腦可以使用多用戶同時登錄時候,每個使用者只允許執行一次exe程式. 例如:一台公用電腦,有多個用戶A.B. 當用戶A進入系統第一次運行C:\XX.exe,OK.第二次運行XX.exe ...
- 使用clipboard.js复制页面内容到剪切板
最近在做一个的智能客服Web端浏览器应用,其中有一项需求是客户在获取系统返回的 答案后点击“复制答案”按钮将答案复制到系统剪切板.本以为这是一个小case,但是发现如果 要对各种主流浏览器都有良好的兼 ...
- SQL求 交集 并集 差集
故事是这样的….. 故事情节: 表 tb_test 有两列, colA , colB; 求 colA , colB 的并交差集… -- 计算并集 SELECT DISTINCT colB FROM t ...
- JavaScript 教程学习进度备忘(二)
备忘:之前,只将“JS 教程”学习完毕,这篇记录:“JS HTML DOM ”.“JS 对象”.“JS Window”.“JS 库” 书签:跳过:另外跳过的内容有待跟进 _______________ ...
- 1005acm罚时
ACM国际大学生程序设计竞赛是由国际计算机学会主办的,一项旨在展示大学生创新能力.团队精神和在压力下编写程序.分析和解决问题能力的年度竞赛.参赛队伍最多由三名参赛队员组成,竞赛中一般命题10-13题, ...
- The remote SSH server rejected X11 forwarding request
两台相同的虚拟机,一台没有错误,一个经常出现警告,内容如下所示: The remote SSH server rejected X11 forwarding request 找了很多方法,最后发现是安 ...
- 用代码将Excel数据导入Sql Server
这里直接用小例子说明. 1.打开VS2010—>文件—>新建—>网站,选择ASP.NET空网站并设置存放路径以创建空网站.(我这里路径设置为D:\excelEduceToSql) 2 ...