一篇笔记带你快速掌握面向对象的Javascript(纯手打)
/**
* 创建对象
*/ //1.工厂模式
//特点:
//创建的对象无法识别其对象类型,不支持instanceof等判断方法,无法标识不同的对象
function createObj(name,sex,age){
var obj = new Object();
obj.name = name;
obj.sex = sex;
obj.age = age;
obj.show = function(){
alert(this.name);
}
return obj;
}
var obj = createObj("jackie","male",29);
console.log(obj); //2.构造函数模式
//特点:
//使用new创建对象,因此可以使用instanceof,constructor等来识别对象类型
//new创建的对象,内部会有一个__proto__指针指向构造函数的prototype
//如果漏写new,会导致构造函数内部this指针指向window,导致严重错误
//缺点是无法复用公用的方法,创建多个对象时会重复创建多次公用方法
function CreateObj(name,sex,age){
this.name = name;
this.sex = sex;
this.age = age;
this.show = function(){
alert(this.name);
}
} var obj = new CreateObj("jackie","male",29);
console.log(obj);
console.log(obj.constructor); //Function CreateObj
console.log(obj instanceof CreateObj); //true
console.log(obj instanceof Object); //true
console.log(obj.__proto__ === CreateObj.prototype); //true //3.原型模式
//所有属性方法均绑在原型上,这样生成的对象打印是空,但是属性和方法可以通过原型链查找获取到
//在实例上重写原型链已有属性不会改变原型链上的对应属性,就算设置为null也不行,只能屏蔽掉
//屏蔽掉原型属性后想恢复需要使用delete操作符移除对应实例属性
//多个实例共享绑在原型链上的属性和方法,且原型只需要初始化的时候创建一次而已
//可以使用instanceof,constructor,isPrototypeOf等方法来判断对象所属
//缺点在于属性无法传参数,导致创建的对象属性都相同,方法也是共享,无法体现出对象的独一性
//引用类型的属性多个对象会同时改变,例如数组
function CreateObj(){ }
CreateObj.prototype.name = "jackie";
CreateObj.prototype.sex = "male";
CreateObj.prototype.age = 29;
CreateObj.prototype.show = function(){
alert(this.name);
} var obj = new CreateObj();
var obj2 = new CreateObj();
console.log(obj); // {}
console.log(obj.name); // jackie
console.log(obj2.name); //jackie
obj2.name = "tommy";
console.log(obj2.name); //tommy
delete obj2.name;
console.log(obj2.name); //jackie
console.log(obj.show === obj2.show); //true
console.log(obj.constructor); //Function CreateObj
console.log(obj2 instanceof CreateObj); //true
console.log(CreateObj.prototype.isPrototypeOf(obj)); //true
console.log(CreateObj.prototype.constructor === CreateObj); //true
CreateObj.prototype.arr = [1,2,3];
obj.arr.push(4);
console.log(obj2.arr); //[1,2,3,4] //4.组合构造函数原型模式
//属性使用构造函数传参来构造,公用方法绑定在prototype上实现复用
//可以使用instanceof,constructor,hasOwnProperty,in等方法来判断对象所属
//此时引用类型数据存在构造函数内,不存在不同对象相互影响的问题
//结合了构造函数和原型链的优势,解决了两者存在的问题,是目前最为常用的一种方式
function CreateObj(name,sex,age){
this.name = name;
this.sex = sex;
this.age = age;
this.arr = [1,2,3];
}
CreateObj.prototype.show = function(){
alert(this.name);
} var obj = new CreateObj('jackie','male',29);
console.log(obj);
console.log(obj.constructor); //Function CreateObj
console.log(obj instanceof CreateObj); //true
console.log(obj.hasOwnProperty('sex')); //true
console.log('show' in obj); //true
var obj2 = new CreateObj('jackie','male',29);
obj.arr.push(4);
console.log(obj.arr); //[1,2,3,4]
console.log(obj2.arr); //[1,2,3] //5.单例模式
//只能创建一次,常用于单页面,实现某个页面的具体功能
//相对于面向过程的散乱写法,这种写法可维护性更好
var CreateObj = {
name: 'jackie',
sex: 'male',
age: 29,
init: function(){
console.log(this.name,this.sex,this.age);
}
} CreateObj.init(); //jackie male 29 /**
* 继承
*/ //1.原型链继承
//将父类实例赋值给子类的prototype,这样父类的所有方法和属性(无论是构造函数还是原型上定义的)全部都继承给了子类
//使用instanceof发现子类是子类,父类,Object类的实例,这是由于原型链的关系,一层层往内找,最后终点是Object类
//继承后子类实例的constructor会被指向父类,因此如果需要,可以手动修正将constructor指回子类,虽然指回后的是可枚举的constructor
//由于是绑定在原型链上的继承,因此引用类型数据在多个实例内是共享的,会相互影响
//一个严重缺陷,子类构造函数无法传参数,因为继承来的属性全部在原型链上,和构造函数没有联系,因此继承后子类所有对象的属性都相同
function Super(age){
this.name = 'yinshawn';
this.age = age;
this.arr = [1,2,3];
}
Super.prototype.show = function(){
console.log(this.name);
}
function Sub(){ }
Sub.prototype = new Super(29); var sub = new Sub();
console.log(sub.name); //yinshawn
console.log(sub.age); //29
sub.show(); //yinshawn
console.log(sub.constructor); //Function Super
Sub.prototype.constructor = Sub;
console.log(sub.constructor); //Function Sub
console.log(sub instanceof Sub); //true
console.log(sub instanceof Super); //true
console.log(sub instanceof Object); //true
var sub2 = new Sub();
sub.arr.push(4);
console.log(sub2.arr); //[1,2,3,4] //2.构造函数继承
//通过call或apply在子类构造函数里调用父类构造函数,call(this,param1,param2,param3)或apply(this,arguments)均可
//此类继承可以在子类的构造函数内传参,使生成的对象真正拥有自己的属性
//由于是在构造函数内,因此引用类数据不会有多个对象相互影响的问题
//依然可以使用constructor和instanceof来判断对象所属
//一个严重缺陷,所有需要继承的属性和方法都需要写在构造函数内,原型链上的方法属性无法继承,如果全部写在构造函数内,无法实现方法复用
function Super(age,sex){
this.name = "jackie";
this.age = age;
this.sex = sex;
this.arr = [1,2,3];
}
Super.prototype.show = function(){
console.log(this.name);
}
function Sub(age,sex){
Super.call(this,age,sex);
Super.apply(this,arguments);
} var sub = new Sub(29);
console.log(sub.name); //jackie
console.log(sub.age); //29
console.log(sub.show); //undefined
var sub2 = new Sub(29,'female');
console.log(sub2.sex); //female
sub2.arr.push(4);
console.log(sub.arr); //[1,2,3]
console.log(sub2.arr); //[1,2,3,4]
console.log(sub instanceof Super); //true
console.log(sub.constructor); //Function Sub //3. 组合构造函数原型继承
//即结合构造函数继承和原型继承,两者合二为一
//此时子类构造函数可以传参,不仅可以继承构造函数内的属性方法,也可以继承原型链上的属性方法,自己可以灵活分配
//唯一美中不足的是会执行两次父类构造函数,而且会生成两组相同的属性,同时存在于原型链和构造函数内
function Super(age,sex){
this.name = "jackie";
this.age = age;
this.sex = sex;
this.arr = [1,2,3];
}
Super.prototype.show = function(){
console.log(this.name);
}
function Sub(age,sex){
Super.call(this,age,sex);
Super.apply(this,arguments);
}
Sub.prototype = new Super();
Object.defineProperty(Sub.prototype,"constructor",{
value: 'Sub',
enumerable : false
}); var sub = new Sub(29,'male');
console.log(sub.age); //29
console.log(sub.show); //Function
console.log(sub instanceof Super); //true
console.log(sub.constructor); //Sub //4.单对象浅复制继承
//不使用构造函数,直接实现两个对象之间的继承,使用ES5的create方法来继承父类,并自己添加新属性或重载父类属性
//若考虑兼容性问题,则可自定义函数,实现类似效果
//使用非标准的__proto__也可实现简单继承
var Super = {
name: 'jackie',
age: 29
} //方法1
var Sub = Object.create(Super,{
sex : {
value: 'male'
},
age: {
value: 92
}
}); console.log(Sub.name); //jackie
console.log(Sub.sex); //male
console.log(Sub.age); //92 //方法2
function create2(obj){
var F = function(){};
F.prototype = obj;
return new F();
} var Sub = create2(Super);
Sub.age = 92;
console.log(Sub.name); //jackie
console.log(Sub.age); //92 //方法3
var Sub = {
__proto__: Super,
age: 92
} console.log(Sub.name); //jackie
console.log(Sub.age); //92 //5.寄生组合式完美继承
//目前最完美的继承方式,主要在构造函数原型组合继承基础上改动
//改动了其中原型继承里将父类实例赋值给子类的prototype这一段,这里产生的缺陷也就是多调用了一次父类构造函数,而且将原本构造函数内的属性记录在了原型里
//改动方向是避免调用构造函数,而是使用别的方法来得到父类实例,且这个实例上没有跟构造函数相关的属性,例如Object,Object.create,自定义浅复制函数等
//主要思路就是将父类prototype通过Object方法或create方法生成一个只带有父类原型属性的副本,将这个副本的constructor指正后赋值给子类prototype
//这种方法是目前最完美的方法,无明显缺陷
function Super(age,sex){
this.name = "jackie";
this.age = age;
this.sex = sex;
this.arr = [1,2,3];
}
Super.prototype.show = function(){
console.log(this.name);
}
function Sub(age,sex){
Super.call(this,age,sex);
Super.apply(this,arguments);
}
var prototype = Object(Super.prototype); //得到一个父类实例
prototype.constructor = Sub;
Sub.prototype = prototype; var sub = new Sub(28,'male');
console.log(sub.show); //Function
console.log(sub.age); //28
console.log(sub instanceof Super); //true
一篇笔记带你快速掌握面向对象的Javascript(纯手打)的更多相关文章
- 一篇笔记带你梳理JVM工作原理
首先要了解的 数据类型 Java虚拟机中,数据类型可以分为两类:基本类型和引用类型. 基本类型的变量保存原始值,即:他代表的值就是数值本身:而引用类型的变量保存引用值.“引用值”代表了某个对象的引用, ...
- Flutter学习笔记(8)--Dart面向对象
如需转载,请注明出处:Flutter学习笔记(7)--Dart异常处理 Dart作为高级语言,支持面向对象的很多特性,并且支持基于mixin的继承方式,基于mixin的继承方式是指:一个类可以继承自多 ...
- (转)Python成长之路【第九篇】:Python基础之面向对象
一.三大编程范式 正本清源一:有人说,函数式编程就是用函数编程-->错误1 编程范式即编程的方法论,标识一种编程风格 大家学习了基本的Python语法后,大家就可以写Python代码了,然后每个 ...
- JavaScript学习笔记(十六)——面向对象编程
在学习廖雪峰前辈的JavaScript教程中,遇到了一些需要注意的点,因此作为学习笔记列出来,提醒自己注意! 如果大家有需要,欢迎访问前辈的博客https://www.liaoxuefeng.com/ ...
- 两篇文章带你走入.NET Core 世界:Kestrel+Nginx+Supervisor 部署上云服务器(二)
背景: 上一篇:两篇文章带你走入.NET Core 世界:CentOS+Kestrel+Ngnix 虚拟机先走一遍(一) 已经交待了背景,这篇就省下背景了,这是第二篇文章了,看完就木有下篇了. 直接进 ...
- 【转】C#单元测试,带你快速入门
[转]C#单元测试,带你快速入门 注:本文示例环境 VS2017 XUnit 2.2.0 单元测试框架 xunit.runner.visualstudio 2.2.0 测试运行工具 Moq 4.7.1 ...
- python采用pika库使用rabbitmq总结,多篇笔记和示例
这一段时间学习了下rabbitmq,在学习的过程中,发现国内关于python采用pika库使用rabbitmq的资料很少,官网有这方面的资料,不过是都英文的.于是笔者结合自己的理解,就这方面内容写了一 ...
- python采用pika库使用rabbitmq总结,多篇笔记和示例(转)
add by zhj:作者的几篇文章参考了Rabbitmq的Tutorials中的几篇文章. 原文:http://www.01happy.com/python-pika-rabbitmq-summar ...
- 谁再问elasticsearch集群Red怎么办?把这篇笔记给他
前言 可能你经历过这些Red. ...等等 那ES的Red是神么意思? 这里说的red,是指es集群的状态,一共有三种,green.red.yellow.具体含义: 冷静分析 从上图可知,集群red是 ...
随机推荐
- 1.Two Sum(c++)(附6ms O(n) accepted 思路和代码)
问题描述: Given an array of integers, return indices of the two numbers such that they add up to a speci ...
- 【Oracle】Oracle日期格式详解
本文章没有经过验证,纯属使用CV大法.感谢原创的大牛. to_date("要转换的字符串","转换的格式") 两个参数的格式必须匹配,否则会报错. 即按照第 ...
- powershell使用
主要语法点: -match -notmatch -replace -join -split -and -or -xor -not ! +.-.*./.% =.+=.-=.*=./=.%= -eq.-n ...
- 关于datepicker只显示年、月、日的设置
关键时侯,还得看官方文档.花了半个多小时,找了网上一大堆答复,然后一一验证,90%没有能解决问题. 先给出官方文档的URL: http://bootstrap-datepicker.readthedo ...
- xtrabackup 使用说明(续)
背景: 关于物理备份工具xtrabackup的一些说明可以先看之前写过的文章说明:xtrabackup 安装使用.现在xtrabackup版本升级到了2.4.4,相比之前的2.1有了比较大的变化:in ...
- DIV+CSS布局
宽度自适应两列布局 <!DOCTYPE html> <html> <head> <meta charset="gbk"> <t ...
- $_session (应用)
登录: 封装类(用于连接数据库)代码中创建一个对象最好可以重复使用 <?php class DBDA { public $host="localhost"; public $ ...
- [原创]用命令行工具删除TFS2010服务器上的工作区信息
下面的示例显示有关所有计算机上的所有用户已在地址 http://myserver:8080/tfs/DefaultCollection 上的以下团队项目集合中创建的所有工作区的列表. c:\proje ...
- Mysql InnoDB 共享表空间和独立表空间
前言:学习mysql的时候总是习惯性的和oracle数据库进行比较.在学习mysql InnoDB的存储结构的时候也免不了跟oracle进行比较.Oracle的数据存储有表空间.段.区.块.数据文件: ...
- Redis
1. sds类型 sds为一种抽象数据结构 typedef char *sds;struct sdshdr { // buf 已占用长度int len; // buf 剩余可用长度int free; ...