/**
* 创建对象
*/ //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(纯手打)的更多相关文章

  1. 一篇笔记带你梳理JVM工作原理

    首先要了解的 数据类型 Java虚拟机中,数据类型可以分为两类:基本类型和引用类型. 基本类型的变量保存原始值,即:他代表的值就是数值本身:而引用类型的变量保存引用值.“引用值”代表了某个对象的引用, ...

  2. Flutter学习笔记(8)--Dart面向对象

    如需转载,请注明出处:Flutter学习笔记(7)--Dart异常处理 Dart作为高级语言,支持面向对象的很多特性,并且支持基于mixin的继承方式,基于mixin的继承方式是指:一个类可以继承自多 ...

  3. (转)Python成长之路【第九篇】:Python基础之面向对象

    一.三大编程范式 正本清源一:有人说,函数式编程就是用函数编程-->错误1 编程范式即编程的方法论,标识一种编程风格 大家学习了基本的Python语法后,大家就可以写Python代码了,然后每个 ...

  4. JavaScript学习笔记(十六)——面向对象编程

    在学习廖雪峰前辈的JavaScript教程中,遇到了一些需要注意的点,因此作为学习笔记列出来,提醒自己注意! 如果大家有需要,欢迎访问前辈的博客https://www.liaoxuefeng.com/ ...

  5. 两篇文章带你走入.NET Core 世界:Kestrel+Nginx+Supervisor 部署上云服务器(二)

    背景: 上一篇:两篇文章带你走入.NET Core 世界:CentOS+Kestrel+Ngnix 虚拟机先走一遍(一) 已经交待了背景,这篇就省下背景了,这是第二篇文章了,看完就木有下篇了. 直接进 ...

  6. 【转】C#单元测试,带你快速入门

    [转]C#单元测试,带你快速入门 注:本文示例环境 VS2017 XUnit 2.2.0 单元测试框架 xunit.runner.visualstudio 2.2.0 测试运行工具 Moq 4.7.1 ...

  7. python采用pika库使用rabbitmq总结,多篇笔记和示例

    这一段时间学习了下rabbitmq,在学习的过程中,发现国内关于python采用pika库使用rabbitmq的资料很少,官网有这方面的资料,不过是都英文的.于是笔者结合自己的理解,就这方面内容写了一 ...

  8. python采用pika库使用rabbitmq总结,多篇笔记和示例(转)

    add by zhj:作者的几篇文章参考了Rabbitmq的Tutorials中的几篇文章. 原文:http://www.01happy.com/python-pika-rabbitmq-summar ...

  9. 谁再问elasticsearch集群Red怎么办?把这篇笔记给他

    前言 可能你经历过这些Red. ...等等 那ES的Red是神么意思? 这里说的red,是指es集群的状态,一共有三种,green.red.yellow.具体含义: 冷静分析 从上图可知,集群red是 ...

随机推荐

  1. PHP 数据库连接工具类(MySQLI函数包装)

    ====================mysql===================== <?php class mysql { private $mysqli; private $resu ...

  2. PCA、ZCA白化

    白化是一种重要的预处理过程,其目的就是降低输入数据的冗余性,使得经过白化处理的输入数据具有如下性质:(i)特征之间相关性较低:(ii)所有特征具有相同的方差. 白化又分为PCA白化和ZCA白化,在数据 ...

  3. WPF相关开源项目

    MahApps 排名第一的是MahApps框架. 该框架不错.详细信息请去官网. cefsharp 能让你在应用中嵌入谷歌浏览器页

  4. JAVA基础学习——1.2 环境搭建 之eclipse安装及中文化

    安装好jdk,配置好环境变量以后,下面就可以进行安装eclipse了. 闲话少说,eclipse下载地址:http://www.eclipse.org/downloads/ 不大用关注checksum ...

  5. Nodejs实现简单的反向代理

    var http = require('http'), httpProxy = require('http-proxy'); // 新建一个代理 Proxy Server 对象 var proxy = ...

  6. LeetCode 167 Two Sum II - Input array is sorted

    Problem: Given an array of integers that is already sorted in ascending order, find two numbers such ...

  7. Transaction (Process ID xxx) was deadlocked on lock

    Transaction (Process ID 161) was deadlocked on lock | communication buffer resources with another pr ...

  8. 缓存淘汰算法--LRU算法

    1. LRU1.1. 原理 LRU(Least recently used,最近最少使用)算法根据数据的历史访问记录来进行淘汰数据,其核心思想是"如果数据最近被访问过,那么将来被访问的几率也 ...

  9. *****linux下redis安装

    我用的系统是:redhat [root@infa ~]# wget http://download.redis.io/releases/redis-2.8.12.tar.gz tar xzf redi ...

  10. java Clone 的心得记录

    我看有些类并没有实现Cloneable接口,这种情况下调用clone()方法也不try catch也不throws: 但是如果我自己这样搞,也不实现Cloneable,接口,直接调用clone()方法 ...