此篇文章主要是提炼《JavaScript高级程序设计》中第六章的一些内容。

一:JS中OOP相关的概念

开始之前先总结JS中OOP相关的一些概念:

构造函数:JS中的构造函数就是普通的函数,当JS中的函数使用new调用时,这个函数就是构造函数。构造函数调用与普通函数调用相比会有以下两点不同:

① 在进入构造函数时,会先创建一个对象,并将构造函数的作用域赋值给这个对象(this指向这个对象)

② 在退出构造函数前,会默认返回创建的对象(返回this)

原型对象:每个函数都会有一个prototype属性,函数的prototype属性指向的就是(构造)函数的原型对象。默认情况下函数的原型对象都会有一个constructor属性,指向函数自身。

其实,JS中所有的对象都会有constructor属性,默认指向Object。

function foo(){}

//所有的函数都具有prototype属性
//所有函数的原型对象(函数的prototype属性)默认的constructor属性指向函数自身
foo.prototype.constructor === foo; //所有对象都具有constructor属性,默认指向Object
({}).constructor === Object; //对象实例内部都会有一个[[prototype]]指针,指向对象在创建时所依赖的原型对象
(new foo()).__proto__ === foo.prototype
({}).__proto__ === Object.prototype;
foo.prototype === (new foo).__proto__;
(new foo).__proto__.constructor === foo;

实例: 使用new产生的一个具体的对象

二: 封装类(创建自定义类型)

使用构造函数+原型模式封装类。具体做法是:

① 把实例属性(不共享的属性)写在构造函数中

② 把共享属性(包含constructor)写在函数原型对象中

function Animal(opts) {
this.cate = opts.cate;
} Animal.prototype = {
constructor: Animal,
shout :function () {
console.log('animal shouted');
}
}
//为了封装看起来更优雅,也可以写成下面这样
function Animal(opts) { this.cate = opts.cate; if(typeof this.shout !== 'function') {
//这样直接将一个对象赋值给Animal.prototype会断开进入构造函数时创建的对象的__proto__属性与原型对象的链接
//所以实际new出来的第一个对象的__proto__上面不会有原型对象上的方法
//解决办法是手动在后面调用一次构造函数或像下面那样增加方法就不会断开构造函数时创建的对象的__proto__属性与原型对象的链接
/**
* Animal.prototype.shout = function() {}
* Animal.prototype.getCate = function() {}
*/
Animal.prototype = {
constructor: Animal,
shout :function () {
console.log('animal shouted');
},
getCate: function() {
return this.cate;
},
setCate: function(cate) {
this.cate = cate;
}
}
} }
//手动new一次Animal
new Animal();

这种封装的缺点:没有实现访问权限控制,所有的一切都是public的。

三:继承

使用借用构造函数+原型链接实现继承

function Animal(opts) {
this.cate = opts ? opts.cate : undefined;
if(typeof this.shout !== 'function') {
Animal.prototype = {
constructor: Animal,
shout :function () {
console.log('animal shouted');
},
getCate: function() {
return this.cate;
},
setCate: function(cate) {
this.cate = cate;
}
}
} }
//手动new一次Animal
new Animal(); //定义Dog类,并让其从Animal继承
function Dog(opts) { //继承Animal中的属性
Animal.call(this, opts); //增加Dog的属性
this.name = opts.name; //...
} Dog.prototype = new Animal();
Dog.constuctor = Dog;
Dog.prototype.getName = function() {
return this.name;
}

缺点很明显:Dog.prototype = new Animal(); 要实例化Dog会先调用一次Animal(),同时在new Dog()时,在Dog的构造函数中又会调用一次Animal(), Animal.call(this, opts);

由于Dog.prototype = new Animal(); 只是想拿到Animal原型对象上的方法,所以我们可以改成这样,Dog.prototype = Animal.prototype; 但改成这样后,Dog.prototype与

Animal.prototype实际就都指向同一个对象了,所以Animal的实例也会有getName()方法。但我们可以先创建一个对象,再把Animal.prototype上的属性拷贝来过,再赋值给

Dog.prototype。

function Animal(opts) {
this.cate = opts ? opts.cate : undefined;
} Animal.prototype = {
constructor: Animal,
shout :function () {
console.log('animal shouted');
},
getCate: function() {
return this.cate;
},
setCate: function(cate) {
this.cate = cate;
}
} //定义Dog类,并让其从Animal继承
function Dog(opts) { //继承Animal中的属性
Animal.call(this, opts); //增加Dog的属性
this.name = opts.name; //...
} Dog.prototype = (function() {
var DogProto = {}, AnimalProto = Animal.prototype, key;
for(key in AnimalProto) {
AnimalProto.hasOwnProperty(key)
DogProto[key] = AnimalProto[key];
}
return DogProto;
})();
Dog.prototype.constructor = Dog;
Dog.prototype.getName = function() {
return this.name;
}

这样改了后,也还是有缺点:  new Dog instanceof Animal;会返回false。但如果我们只关注对象能做什么,而不是对象的类是什么(鸭式辨型编程)这样做还是达到了我们想要的效果。

还有如果我们平时想使用一些带有自己方法的原生对象,但我们又不想去直接扩展原生对象的prototype,我们可以像下面这样做:

function enhancedString(str) {
str = new String(str); //增加我们的方法
!str.statsWith && (str.startsWith = function(target) {
return this.indexOf(target) === 0;
}); //... return str;
} //测试:
var str = new enhancedString('test');
//可以使用string原生的方法
console.log(str.length);//4
console.log(str.slice(1));//est
//也可以使用我们在string上面扩展的方法
console.log(str.startsWith('t')); //true

小结JS中的OOP(中)的更多相关文章

  1. 不会JS中的OOP,你也太菜了吧!(第二篇)

    一.你必须知道的 1> 原型及原型链在继承中起到了关键的作用.所以你一定要理解他们.2> 不会JS中的OOP,你也太菜了吧!(第一篇) 二.继承的6种方法 1> 原型链继承 原型链继 ...

  2. js oop中的三种继承方法

    JS OOP 中的三种继承方法: 很多读者关于js opp的继承比较模糊,本文总结了oop中的三种继承方法,以助于读者进行区分. <继承使用一个子类继承另一个父类,子类可以自动拥有父类的属性和方 ...

  3. js中对arry数组的各种操作小结 瀑布流AJAX无刷新加载数据列表--当页面滚动到Id时再继续加载数据 web前端url传递值 js加密解密 HTML中让表单input等文本框为只读不可编辑的方法 js监听用户的键盘敲击事件,兼容各大主流浏览器 HTML特殊字符

    js中对arry数组的各种操作小结   最近工作比较轻松,于是就花时间从头到尾的对js进行了详细的学习和复习,在看书的过程中,发现自己平时在做项目的过程中有很多地方想得不过全面,写的不够合理,所以说啊 ...

  4. 在Ext JS 5应用程序中如何使用路由

    简介 Ext JS 5是一个重要的发布版本,它提供了许多新特性来创建丰富的.企业级的Web应用程序.MVVM和双向数据绑定为开发人员承担了大量的繁重工作.在Ext JS 5种,另一个新特性就是路由,它 ...

  5. 【翻译】在Ext JS 5应用程序中怎样使用路由

    原文:How to Use Routing in Your Ext JS 5 Apps 简单介绍 Ext JS 5是一个重要的公布版本号,它提供了很多新特性来创建丰富的.企业级的Web应用程序.MVV ...

  6. 【翻译】Ext JS 5.0.1 中的新功能

    原文:What's New in Ext JS 5.0.1 今天,我们很高兴的宣布Ext JS 5.0.1发布了!此维护版本基于Sencha社区的反馈做了一些改进.下面让我们来了解一下这些改变. 可访 ...

  7. 【翻译】在Ext JS 5应用程序中如何使用路由

    原文:How to Use Routing in Your Ext JS 5 Apps 简介 Ext JS 5是一个重要的发布版本,它提供了许多新特性来创建丰富的.企业级的Web应用程序.MVVM和双 ...

  8. Js/Jquery获取iframe中的元素

    转载: Js/Jquery获取iframe中的元素 - - ITeye技术网站http://java-my-life.iteye.com/blog/1275205 在web开发中,经常会用到ifram ...

  9. ActiveX(二)Js 监听 ActiveX中的事件

    在上一篇随笔:ActiveX(一)第一个简单的Demo 中,已经可以实现 js 单向调用 ActiveX 中的方法,在很多情况下ActiveX中的方法的执行时相对耗时.耗性能的.在这样的情况下.Act ...

  10. js中获取URL中指定的查询字符串

    js中获取URL中指定的搜索字符串,主要利用location对象实现,废话少说,上代码. function getSearchString(key) { // 获取URL中?之后的字符 var str ...

随机推荐

  1. lintcode:打劫房屋

    题目 打劫房屋 假设你是一个专业的窃贼,准备沿着一条街打劫房屋.每个房子都存放着特定金额的钱.你面临的唯一约束条件是:相邻的房子装着相互联系的防盗系统,且 当相邻的两个房子同一天被打劫时,该系统会自动 ...

  2. SPRING IN ACTION 第4版笔记-第十一章Persisting data with object-relational mapping-003编写JPA-based repository( @PersistenceUnit、 @PersistenceContext、PersistenceAnnotationBeanPostProcessor)

    一.注入EntityManagerFactory的方式 package com.habuma.spittr.persistence; import java.util.List; import jav ...

  3. iOS 动态特性和RunTime

    过去的几年中涌现了大量的Objective-C开发者.有些是从动态语言转过来的,比如Ruby或Python,有些是从强类型语言转过来的,如Java或C#,当然也有直接以Objective-C作为入门语 ...

  4. logstash_agent.conf 语法注意事项

    编写配置文件时要注意语法,如新版本的logstash对参数host变更为hosts,去除了port参数等. [root@localhost logstash]# cat logstash_agent. ...

  5. opencv 金字塔图像分割

    我所知的opencv中分割函数:watershed(只是看看效果,不能返回每类pixel类属),cvsegmentImage,cvPyrSegmentation(返回pixel类属) 金字塔分割原理篇 ...

  6. post提交/文件上传服务器修改

    第一步:修改在php5下POST文件大小的限制   1.编修php.ini   找到:max_execution_time = 30 ,这个是每个脚本运行的最长时间,单位秒,修改为: max_exec ...

  7. jdk、apache-ant结合yuicompressor配置的CSS与JS合并压缩工具

    前序:网上很多css与js合并打包工具,其中最流行的就是ant结合yui-compressor,鉴于学习与工作需要今天就学习了一下这种方式,供大家学习交流. 步骤:1.安装jdk,并配置其变量环境:有 ...

  8. 最短JS判断是否为IE6(IE的写法) (转)

    常用的 JavaScript 检测浏览器为 IE 是哪个版本的代码,包括是否是最人极端厌恶的 ie6 识别与检测. 代码如下: var isIE = !!window.ActiveXObject; v ...

  9. 如何实现上下左右键盘控制焦点使之落在相邻文本框或下拉框中-Web开发/JavaScript

    我用jquery只实现了文本框的移动(暂时上下移动等同于左右移动) $(function () { var cols = 1;//按一下跳几个控件 var obj = $("input[id ...

  10. Java WEB安全问题及解决方案

    1.弱口令漏洞   解决方案:最好使用至少6位的数字.字母及特殊字符组合作为密码.数据库不要存储明文密码,应存储MD5加密后的密文,由于目前普通的MD5加密已经可以被破解,最好可以多重MD5加密.   ...