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.属性 ...
随机推荐
- Qt/C++加载不同的地图控件/地图类型/缩放标尺/缩略图/比例尺/实时路况/全景视图等
一.前言说明 在展示地图的时候,有些常规的操作,比如调整地图的缩放级别,切换到卫星图等,希望能够在地图上直接操作实现,于是就有了一堆地图控件,可以根据自己的需求动态的添加和删除,这样就更直接更快捷,而 ...
- [转]基于图像的三维模型重建4——增量SFM
内容 几种BA的形式 同时优化相机和三维点 优化相机 只优化三维点 单目相机 增量运动恢复结构(Incremental SFM) 运动恢复结构的几个问题 几种BA的形式 数学模型 n个三维点和m个相机 ...
- OpenMMLab AI实战营 第六课笔记
OpenMMLab AI实战营 第六课笔记 目录 OpenMMLab AI实战营 第六课笔记 1.什么是语义分割 1.1 语义分割的应用 1.1.1 应用:无人驾驶汽车 1.1.2 应用:人像分割 1 ...
- linux输出文件名及全路径
有时候需要输出一个文件夹下的文件名及所以绝对路径,在网上找到是这个命令 ls | sed "s:^:`pwd`/:" 看命令不难理解,先是ls列出所有文件名,再使用管道符进行后续操 ...
- 一篇解决编译原理大作业,基于Flex、Bison设计编译器(含语法分析树和符号表)
1.工具简单介绍 Flex 和 Bison 是编译器开发中常用的两个工具,分别用于生成词法分析器和语法分析器.它们通常一起使用,共同完成源代码的词法分析和语法分析工作. Flex: Flex通过读取一 ...
- python基础学习6和7
模块类与对象 模块 内置模块 time, random, os, json 第三方模块 requests, pandas, numpy,.... 自定义模块 xxx.py 常见的内置模块 hashli ...
- java加密算法入门(四)-加密算法汇总
如基本的单向加密算法: BASE64 严格地说,属于编码格式,而非加密算法 MD5(Message Digest algorithm 5,信息摘要算法) SHA(Secure Hash Algorit ...
- Elasticsearch中数据是如何存储的
前言 很多使用Elasticsearch的同学会关心数据存储在ES中的存储容量,会有这样的疑问:xxTB的数据入到ES会使用多少存储空间.这个问题其实很难直接回答的,只有数据写入ES后,才能观察到实际 ...
- Kotlin:【接口】【抽象类】
- 探秘Transformer系列之(1):注意力机制
探秘Transformer系列之(1):注意力机制 0x00 概述 因为各种事情,好久没有写博客了,之前写得一些草稿也没有时间整理(都没有时间登录博客和微信,导致最近才发现好多未读消息和私信,在这里和 ...