javascript 用函数实现“继承”
一、知识储备:
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 用函数实现“继承”的更多相关文章
- JavaScript中函数的继承
大多OOP语言都支持两种继承方式: 接口继承和实现继承 ,而ECMAScript中无法实现接口继承,ECMAScript只支持实现继承,而且其实现继承主要是依靠 原型链 来实现. 1.原型链 基本思想 ...
- javascript的函数、创建对象、封装、属性和方法、继承
转自原文javascript的函数.创建对象.封装.属性和方法.继承 一,function 从一开始接触到js就感觉好灵活,每个人的写法都不一样,比如一个function就有N种写法 如:functi ...
- 玩转JavaScript OOP[4]——实现继承的12种套路
概述 在之前的文章中,我们借助构造函数实现了"类",然后结合原型对象实现了"继承",并了解了JavaScript中原型链的概念. 理解这些内容,有助于我们更深入 ...
- JavaScript对寄生组合式继承的理解
有关JavaScript的几种继承方式请移步JavaScript的几种继承方式 原型链的缺陷 SubType.prototype = new SuperType(); 这样做的话,SuperType构 ...
- web前端学习(二) javascript对象和原型继承
目录 1. JavaScrpt对象 2. 原型对象和继承 3. 对象的克隆 (1)javascript对象 在JS中,对象是属性的容器.对于单个对象来说,都由属性名和属性值构成:其中属性名需要是标识符 ...
- 【面试必备】javascript的原型和继承
原型.闭包.作用域等知识可以说是js中面试必考的东西,通过你理解的深度也就能衡量出你基本功是否扎实.今天来复习一下javascript的原型和继承,虽说是老生常谈的话题,但对于这些知识,自己亲手写一遍 ...
- Javascript的实例化与继承:请停止使用new关键字
本文同时也发表在我另一篇独立博客 <Javascript的实例化与继承:请停止使用new关键字>(管理员请注意!这两个都是我自己的原创博客!不要踢出首页!不是转载!已经误会三次了!) 标题 ...
- 小白科普之JavaScript的函数
一 概述 1.1 函数声明 (1)function命令 函数就是使用function命令命名的代码区块,便于反复调用.这种声明方式叫做函数的声明(Function Declaration). func ...
- Javascript之对象的继承
继承是面向对象语言一个非常重要的部分.许多OOP语言都支持接口继承和实现继承两种方式.接口继承:继承方法签名:实现继承:继承实际的方法.在ECMAScript中函数是没有签名的,所以也就无法实现接口继 ...
随机推荐
- Ext.form.FormPanel定义的参数说明
1.formId : String (可选的)FORM标签的id(默认是自动生成的). 2.labelWidth : Number 标签的宽度.该属性级联于子容器. 3. itemCls : Stri ...
- 特性扩展:WebActivatorEx
WebActivator: PreApplicationStartMethod 属性,用于标记作为东西您获取 Web 应用程序启动时调用的方法,在Application_Start前. PostApp ...
- [LeetCode] 76. Minimum Window Substring 解题思路
Given a string S and a string T, find the minimum window in S which will contain all the characters ...
- linux下如何执行PHP脚本
Linux 下如何直接执行 php 脚本? 下面是部分 php 命令行参数. 用法 php [-q] [-h] [-s] [-v] [-i] [-f ] | { [args...]} -q 安静模式, ...
- Struct标签
通用标签: 1. property 2. set i. 默认为action scope,会将值放入request和ActionContext中 ii. ...
- zoj3329 One Person Game
One Person Game Time Limit: 1 Second Memory Limit: 32768 KB Special Judge There is a very simple and ...
- 基于粒子群算法求解求解TSP问题(JAVA)
一.TSP问题 TSP问题(Travelling Salesman Problem)即旅行商问题,又译为旅行推销员问题.货郎担问题,是数学领域中著名问题之一.假设有一个旅行商人要拜访n个城市,他必须选 ...
- 前端学习-使用JS库Leaflet.js生成世界地图并获取标注地址经纬度。
介绍:Leaflet是一个开源的JavaScript库,对移动端友好且对地图有很好的交互性. 大小仅仅只有 33 KB, 同时具有大多数地图所需要的特点. Leaflet设计的非常简单易懂, 同时具有 ...
- C语言、Java的编译系统
Java是跨平台的. Java代码的编译是由Java语言的编译器来执行的,执行后生成的是.class文件,该文件是字节码文件. 然后交给虚拟机进行运行,虚拟机是在各个平台上可移植的.从而决定了Java ...
- Codeigniter数据库操作
//查询: $query = $this->db_query("SELECT * FROM table"); ================================ ...