js回忆录(4) -- 对象,构造函数
1.对象 && 构造函数
js是一门基于对象的语言,里边所有的数据类型都可以当对象使唤(当然null和undefined除外),当我们在v8引擎里声明一个对象时会发现每个对象属性里边都有这个东西:

在说明这个属性之前需要先说明一点就是,声明一个对象和new Object 生成对象的结果是一样的,即,所有对象都是Object的实例,每一个实例都会继承它的构造函数上的prototype的属性,而上面的_proto_就是指向这个原型对象的,也就是说:
实例._proto_ = 构造函数.prototype
每个对象上查找属性时要走的流程大体是,查查自己有没有,查查自己的构造函数的prototype上有没有,再查查构造函数的prototype的构造函数的prototype上有没有,依次查找,如此变成了原型链。普通对象上关于原型只有一个_proto_ 属性指向它的构造函数的原型(原型对象),而在一个函数对象上则多了一个prototype属性,这个属性就是用于继承,创建子类共有的属性,方法的比较重要的一个属性。
函数初始化之后原型对象上有constructor和_proto_两个属性,一个指向这个函数一个指向它自己的构造函数的prototype,一般来说是Object.prototype。
构造函数实在是js里边一个有趣的东西,一个函数是不是构造函数不是取决于它的定义,而是取决于它的调用方式。构造函数不需要return语句 ,甚至调用的时候都不需要(),这一点就比较像php了。生成的实例对象私有属性由构造函数定义,共有属性由构造函数的prototype定义。
2.关于JS里的继承
继承其实是一个面向对象的编程语言的概念,JS天生的短板,一般面试的时候回答继承时怎么做,就只是简单的 子类.prototype = 父类.prototype,好了合格了,但是从实际出发,事情远远没有这么简单,首先是constructor的属性得改,然后得考虑到JS引用类型的特性,然后得留下子类已经定义的属性,防止被父类覆盖,所以一个合理的做法是深拷贝,
function inherit( sub,sup ){
let temp = deepCopy(sup.prototype);//深拷贝父类prototype
for( let key in temp ){
if( sub.prototype[key] !==null || sub.prototype[key] !== undefined){//子类中如果已经存在对应属性,则不作操作
}else{
sub.prototype[key] = temp[key]
}
}
function deepCopy(obj){
let result;
if(JSON){
result = JSON.parse(JSON.stringify(obj))
}else{
for( let key in obj ){
result[key] = typeof( obj[key] ) !== 'object'? obj[key] : deepCopy(obj[key])
}
}
return result
}
}
如果已经确定子类中没有要保留的属性,可以用一下司徒正美大佬的继承方法,这是他的anu框架里边的源码的一个方法,很妙啊,我做了适当删减。
function inherit(SubClass, SupClass) {
function Bridge() {}
Bridge.prototype = SupClass.prototype;
var fn = SubClass.prototype = new Bridge();
fn.constructor = SubClass;
}
----------------------------------------2018-5-15更新-----------------------------------------------------------------
本来以为前面几个继承已经实现的差不多了,然而前几天和某位大佬讨论一番之后,却发现上边那个继承的实现方式并不是很完美,首先,js基于原型链的继承其一是出于性能考虑的,如果采用上面我深拷贝的那种方式实现的话,相当于是将父类的共有方法又拷贝了一份,不是很完美,然后这几天结合自己的思考和es6提供的一些方法,可以使用下面的方式更新,方法1:
function parent(){}
function son(){}
Object.setPrototypeOf(son.prototype,parent.prototype);
Object.setPrototypeOf 方法可以设置一个对象的原型对象,进而通过这种方式实现继承。第二种方法是改变__proto__指向,即:
son.prototype.__proto__ = parent.prototype;
然而,以上两种方式mdn都不是很推荐,具体原因可以看看上边setPrototypeOf的链接,这样做的后果就是牵涉到性能问题了,而比较推荐的方法是使用Object.create这个es5就有的方法:
function parent(){}
function son(){}
son.prototype = Object.create( parent.prototype )
Object.create的第一个参数即为新创造的对象的原型对象。
因此通过这种方法实现继承,不光保证了性能,也可以动态的继承父类的公有属性。
js回忆录(4) -- 对象,构造函数的更多相关文章
- js面向对象(对象/类/工厂模式/构造函数/公有和原型)
https://www.cnblogs.com/sandraryan/ 什么是对象 js中一切都是对象(有行为和特征).js允许自定义对象,也提供了内建对象(string date math等) 对象 ...
- js工厂函数创建对象与对象构造函数的理解
工厂函数,顾名思义,就是通过一个"工厂的加工" 来创建一个对象的函数 //工厂函数 function createPerson(name,sex){ sex = sex == '男' ? '女' : ...
- 程序猿都没对象,JS竟然有对象?
现在做项目基本是套用框架,不论是网上的前端还是后端框架,也会寻找一些封装好的插件拿来即用,但还是希望拿来时最好自己过后再回过头了解里面的原理,学习里面优秀的东西,不论代码封装性,还是小到命名. 好吧, ...
- 浅解析js中的对象
浅解析js中的对象 原文网址:http://www.cnblogs.com/foodoir/p/5971686.html,转载请注明出处. 前面的话: 说到对象,我首先想到的是每到过年过节见长辈的时候 ...
- 170104、js内置对象与原生对象
内置对象与原生对象 内置(Build-in)对象与原生(Naitve)对象的区别在于:前者总是在引擎初始化阶段就被创建好的对象,是后者的一个子集:而后者包括了一些在运行过程中动态创建的对象. 原生对象 ...
- JavaScript学习12 JS中定义对象的几种方式
JavaScript学习12 JS中定义对象的几种方式 JavaScript中没有类的概念,只有对象. 在JavaScript中定义对象可以采用以下几种方式: 1.基于已有对象扩充其属性和方法 2.工 ...
- js object(对象)
http://www.cnblogs.com/pingchuanxin/p/5773326.html Object(对象)是在所有的编程语言中都十分重要的一个概念,对于事物我们可以把他们看作是一个对象 ...
- JavaScript学习12 JS中定义对象的几种方式【转】
avaScript学习12 JS中定义对象的几种方式 转自: http://www.cnblogs.com/mengdd/p/3697255.html JavaScript中没有类的概念,只有对象. ...
- JS中有关对象的继承以及实例化、浅拷贝深拷贝的奥秘
一.属性的归属问题 JS对象中定义的属性和方法如果不是挂在原型链上的方法和属性(直接通过如类似x的方式进行定义)都只是在该对象上,对原型链上的没有影响.对于所有实例共用的方法可直接定义在原型链上这样实 ...
- Js中Map对象的使用
Js中Map对象的使用 1.定义 键/值对的集合. 2.语法 mapObj = new Map() 3.备注 集合中的键和值可以是任何类型.如果使用现有密钥向集合添加值,则新值会替换旧值. 4.属性 ...
随机推荐
- ChannelInboundHandlerAdapter和SimpleChannelInboundHandler区别
ChannelInboundHandlerAdapter和SimpleChannelInboundHandler是我们在使用Netty处理Handler时候很常用的两个继承类,虽然说二者实现的功能大致 ...
- 动态改变shiro的Principal属性
因为要保存一些用户名之外的内容在shiro中,所以创建了一个ShiroUser的类,当用户修改了某些属性后,如何动态保存到shiro中: Subject subject = SecurityUtils ...
- Qt编写安防视频监控系统68-兼容Qt4到Qt6
一.前言 为了从Qt4.7兼容到Qt6.2及后续版本,着实花了不少精力,前提也是对自定义控件大全和各种跨平台的轮子组件全部做成了兼容Qt4到Qt6,这样只剩下UI这块需要兼容就好办多了,各个击破战略, ...
- 超实用 JMeter BeanShell Sampler 教程
超实用 JMeter BeanShell Sampler 教程 宝子们,今天咱继续深挖 JMeter 里超厉害的 BeanShell Sampler,这次多来点实际工作中的例子,让你彻底搞懂它! 一. ...
- w3cschool-微信小程序开发文档-API
https://www.w3cschool.cn/weixinapp/weixinapp-network-request.html 微信小程序API 发起请求 发起 HTTPS 网络请求.使用前请注意 ...
- 060_面向过程和面向对象区别 061_对象是什么_对象和数据管理 062_对象和类的关系_属性_成员变量_方法 063_一个典型类的写法和调用_类的UML图入门 064_内存分析详解_栈_堆_方法区_栈帧_程序执行的内存变化过程
060_面向过程和面向对象区别 061_对象是什么_对象和数据管理 062_对象和类的关系_属性_成员变量_方法 public class SxtStu {//定义了一个类,包含的成员变量,属性,方法 ...
- 在线客服的独立产品之路:如何将复杂的 .NET 系统打包到 Docker 镜像,使之能一键上线
我在业余时间开发了一款自己的独立产品:升讯威在线客服与营销系统.陆陆续续开发了几年,从一开始的偶有用户尝试,到如今线上环境和私有化部署均有了越来越多的稳定用户,在这个过程中,我也积累了不少如何开发运营 ...
- 管理虚拟机(virtual-manager)
- 运行jar包时,在命令行中指定依赖的jar包和主类
在一次实验过程中,使用maven打包java项目为jar包,打出来的myexp.jar包只有7KB(我的实验项目正常打出来的包不小于60MB).这时,运行java -jar myexp.jar报错&q ...
- RabbitMQ(一)——简介
RabbitMQ系列 RabbitMQ(一)--简介 RabbitMQ(二)--模式类型 RabbitMQ(三)--简单模式 RabbitMQ(四)--工作队列模式 RabbitMQ(五)--发布订阅 ...