一、知识储备:

1、枚举属性名称的函数:

(1)for...in:可以在循环体中遍历对象中所有可枚举的属性(包括自有属性和继承属性)

(2)Object.keys():返回数组(可枚举的自有属性)

(3)Object.getOwnPropertyNames():所有的自有属性

3、属性的特性:数据属性和存取器属性

(1)数据属性:可写(writable)  可枚举(enumerable)  可配置(configurable)  值(value)

    数据属性只有一个简单的值;

(2)存取器属性: 写入(set)  读取(get)  可枚举(enumerable)  可配置(configurable)

    存取器属性不可写(即没有writable特性)。

    属性有set方法,那这个属性是可写的,有get方法,那这个属性就是可读的。

4、定义属性特性的方法:Object.defineProperty(对象,属性,描述符对象)

5、获取属性的描述符对象:Object.getOwnPropertyDescriptor(对象,属性)

二、示例

1、根据for...in的用法,我们可以写出模拟“继承”的方法:

<script type="text/javascript">
var child={};
var mother={
name:"zhangzhiying",
lastAge:21,
sex:"女"
};
function extend(target,source){
    for(var p in source){
  target[p]=source[p];
    }
    return target;
}
extend(child,mother);
console.log(child); //Object {name: "zhangzhiying", lastAge: 21, sex: "女"}
</script>

2、使用for in来循环遍历原型对象的属性,然后一一赋值给我们的空对象,从而实现了“继承”。这个思路很正确,下面我们来对以上示例进行改造:

<script type="text/javascript">
var child={};
var mother={
name:"zhangzhiying",
lastAge:21,
set age(value){
this.lastAge=value;
},
get age(){
return this.lastAge+1;
},

sex:"女"
};
     mother.age=15; //有set方法,具有可写性
function extend(target,source){
    for(var p in source){
  target[p]=source[p];
    }
    return target;
}
extend(child,mother);
console.log(child); //Object {name: "zhangzhiying", lastAge: 15, age: 16, sex: "女"}
</script>

可以看到代码中使用了一对set,get;其中age是一个存取器属性。

运行的结果:一个不包含set,get的普通对象。 

结论:for  in实现的“继承”不处理set和get ,它把存取器属性(age)转换为一个静态的数据属性。

3、给mother对象设置数据属性

<script type="text/javascript">
var child={};
var mother={
name:"zhangzhiying",
lastAge:21,
set age(value){
this.lastAge=value;
},
get age(){
return this.lastAge+1;
},
sex:"女"
};
Object.defineProperty(mother,"lastAge",{writable:false}); //把lastAge设置成了不可写
mother.age=15; //设置无效,因为lastAge的值不变,所以lastAge+1不变,即age不变
function extend(target,source){
for(var p in source){
target[p]=source[p];
}
return target;
}
extend(child,mother);
console.log(child); //Object {name: "zhangzhiying", lastAge: 21, age: 22, sex: "女"}
child.lastAge=12;    //结果显示lastAge改变,说明child.lastAge没有“继承”到mother.lastAge的特性,我们再用getOwnPropertyDesriptor()方法确认一下
     console.log(Object.getOwnPropertyDescriptor(child,"lastAge")); //Object {value: 12, writable: true, enumerable: true, configurable: true}
console.log(child); //Object {name: "zhangzhiying", lastAge: 12, age: 22, sex: "女"}
</script>

结论:要实现继承,我们还需要解决的问题->“继承”属性特性。

4、完善版本  

<script type="text/javascript">
var child={};
var mother={
name:"zhangzhiying",
lastAge:21,
set age(value){
this.lastAge=value;
},
get age(){
return this.lastAge+1;
},
sex:"女"
};
Object.defineProperty(mother,"lastAge",{writable:false});
mother.age=15;
function extend(target,source){
var names=Object.getOwnPropertyNames(source); //获取所有的属性名
for(var i=0;i<names.length;i++){
if(names[i] in target) continue; //如果这个属性存在,就跳过(原型继承中,如果自有属性和原型对象的属性重名,保留自有属性)
var desc=Object.getOwnPropertyDescriptor(source,names[i]); //获取mother属性的描述符对象(即属性特性的集合,es5中用描述符对象来表示)
Object.defineProperty(target,names[i],desc); //将mother的描述符对象给child的属性定义
}
return target;
}

extend(child,mother);
console.log(child);
child.lastAge=12;
console.log(Object.getOwnPropertyDescriptor(child,"lastAge"));
console.log(child);
</script>

最后的结果:

可以明显看到三次的打印,child“继承”到了set和get,lastAge数值没发生变化,writable也是false了。 

总结:最近在看《javascript权威指南》,总结一点心得,有错误欢迎指正,共同学习进步~

javascript 用函数实现“继承”的更多相关文章

  1. JavaScript中函数的继承

    大多OOP语言都支持两种继承方式: 接口继承和实现继承 ,而ECMAScript中无法实现接口继承,ECMAScript只支持实现继承,而且其实现继承主要是依靠 原型链 来实现. 1.原型链 基本思想 ...

  2. javascript的函数、创建对象、封装、属性和方法、继承

    转自原文javascript的函数.创建对象.封装.属性和方法.继承 一,function 从一开始接触到js就感觉好灵活,每个人的写法都不一样,比如一个function就有N种写法 如:functi ...

  3. 玩转JavaScript OOP[4]——实现继承的12种套路

    概述 在之前的文章中,我们借助构造函数实现了"类",然后结合原型对象实现了"继承",并了解了JavaScript中原型链的概念. 理解这些内容,有助于我们更深入 ...

  4. JavaScript对寄生组合式继承的理解

    有关JavaScript的几种继承方式请移步JavaScript的几种继承方式 原型链的缺陷 SubType.prototype = new SuperType(); 这样做的话,SuperType构 ...

  5. web前端学习(二) javascript对象和原型继承

    目录 1. JavaScrpt对象 2. 原型对象和继承 3. 对象的克隆 (1)javascript对象 在JS中,对象是属性的容器.对于单个对象来说,都由属性名和属性值构成:其中属性名需要是标识符 ...

  6. 【面试必备】javascript的原型和继承

    原型.闭包.作用域等知识可以说是js中面试必考的东西,通过你理解的深度也就能衡量出你基本功是否扎实.今天来复习一下javascript的原型和继承,虽说是老生常谈的话题,但对于这些知识,自己亲手写一遍 ...

  7. Javascript的实例化与继承:请停止使用new关键字

    本文同时也发表在我另一篇独立博客 <Javascript的实例化与继承:请停止使用new关键字>(管理员请注意!这两个都是我自己的原创博客!不要踢出首页!不是转载!已经误会三次了!) 标题 ...

  8. 小白科普之JavaScript的函数

    一 概述 1.1 函数声明 (1)function命令 函数就是使用function命令命名的代码区块,便于反复调用.这种声明方式叫做函数的声明(Function Declaration). func ...

  9. Javascript之对象的继承

    继承是面向对象语言一个非常重要的部分.许多OOP语言都支持接口继承和实现继承两种方式.接口继承:继承方法签名:实现继承:继承实际的方法.在ECMAScript中函数是没有签名的,所以也就无法实现接口继 ...

随机推荐

  1. Unity 官方 Demo: 2DPlatformer 的 SLua 版本。

    9月份时,趁着国庆阅兵的假期,将 Unity 官方 Demo: 2DPlatformer 移植了一个 SLua 版本,并放在了我的 GitHub 账号下:https://github.com/yauk ...

  2. jQuery dataTables 网格

    对于服务器来说,可以通过请求参数来获得当前的操作信息. 类型 名称 说明 int iDisplayStart 显示的起始索引 int iDisplayLength 显示的行数 int iColumns ...

  3. CSS样式学习笔记『W3School』

    1.选择器+声明声明:属性+值eg:h1{color:red;font-size:14px;}颜色:p{color:#ff0000;}p{color:#f00;}p{color:rgb(255,0,0 ...

  4. hadoop作业调优参数整理及原理【转】

    1 Map side tuning参数 1.1 MapTask运行内部原理 当map task开始运算,并产生中间数据时,其产生的中间结果并非直接就简单的写入磁盘.这中间的过程比较复杂,并且利用到了内 ...

  5. cuda(2) 矩阵乘法优化过程

    Created on 2013-8-5URL : http://blog.sina.com.cn/s/blog_a502f1a30101mjch.html@author: zhxfl转载请说明出处 # ...

  6. Centos6.4 openNebula

    OpenNebula 是一套开源的云计算基础管理工具,用来方便管理员在数据中心统一部署.创建.分配和管理大量的虚拟机,企业数据中心可以利用这套工具搭建自己的私有云,为 自己内部提供 IaaS 服务,类 ...

  7. 容联云通讯_提供网络通话、视频通话、视频会议、云呼叫中心、IM等融合通讯能力开放平台。

    容联云通讯_提供网络通话.视频通话.视频会议.云呼叫中心.IM等融合通讯能力开放平台. undefined

  8. Eclipse用法和技巧十二:快速复制一行

    写代码的总有那么个时候需要Ctrl+c,Ctrl+v,在eclipse中如果遇到需要快速在一行代码的上下复制一行的话,有很方便的快捷键可以使用.将光标放到某一行,按住Ctrl+Alt+Down,即可以 ...

  9. 手机变为电脑的摄像头,使像素高清起来-使用DroidCam

    你是不是已经在嫌弃电脑自带的摄像头的渣渣像素呢? 今天给大家安利一个方法:将手机摄像头设置为电脑的摄像头,让像素高清起来,对于搞图像的同志们真是福音啊,尤其是做人脸识别的时候. 方法有很多种,我推荐我 ...

  10. 改变JVM中的参数以提高Eclipse的运行速度

    首先建立评估体系,将workspace里所有的项目close掉,关闭eclipse.优化的用例就是启动eclipse,open一个项目,eclipse会自动build这个项目,保证没有感觉到明显的卡, ...