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由 ...
随机推荐
- ThreadPoolExecutor使用和思考(上)-线程池大小设置与BlockingQueue的三种实现区别
工作中多处接触到了ThreadPoolExecutor.趁着现在还算空,学习总结一下. 前记: jdk官方文档(javadoc)是学习的最好,最权威的参考. 文章分上中下.上篇中主要介绍ThreadP ...
- ASIFormDataRequest 登录
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL: [NSURL URLWithString: @"http: ...
- 嵌入式 busybox自带的tftp、telnet、ftp服务器
a.tftp server服务器配置与使用 方法1: #udpsvd -vE 069 tftpd -c /root& //上面的0表示对所有ip地址都进行侦听 方法2: #vi/etc/ine ...
- iOS 复选框风格转换 Switchery 开关效果
Switchery 是个简单的 JavaScript 组件,只要几个简单的步骤就可以帮助用户把默认的 HTML 复选框转换成漂亮 iOS 7 样式风格.用户可以很方便的自定义这种转换,所以可以很好的配 ...
- Java并发编程-总纲
Java 原生支持并发,基本的底层同步包括:synchronized,用来标示一个方法(普通,静态)或者一个块需要同步执行(某一时刻,只允许一个线程在执行代码块).volatile,用来标识一个变量是 ...
- static用法总结
C++的static有两种用法:面向过程程序设计中的static和面向对象程序设计中的static.前者应用于普通变量和函数,不涉及类:后者主要说明static在类中的作用. 一.面向过程设计中的st ...
- offer--链表反转和从尾到头打印链表
这个是高频的面试题,今天总结了一些.反转链表用三个指针实现,返回新链表的头节点:而从尾到头打印,应用栈实现,返回vector整个链表. //题目描述 // //输入一个链表,反转链表后,输出链表的所有 ...
- js运动 分享到
<!doctype html> <html> <head> <meta charset = "utf-8"> <title&g ...
- CSRF的攻击与防御(转)
add by zhj:CSRF之所有发生,是因为http请求中会自动带上cookies,我的解决办法是:前端不要将数据放在cookie中,而是放在其它本地存储 (HTML5中称之为Web Storag ...
- ICON的设计很重要
ICON的设计很重要 发布者: wuye | 发布时间: 2014-12-19 17:45| 评论数: 0 游戏类型:手游游戏/平板游戏 设计类型:[功能/模块/UI] 作者:小金狮的UI分享 每个 ...