• 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权威指南》,总结一点心得,有错误欢迎指正,共同学习进步~

  • 相关阅读:
    Fluent动网格【8】:网格节点运动案例
    Fluent动网格【7】:网格节点运动
    Fluent动网格【6】:部件变形案例
    Fluent动网格【5】:部件变形
    Fluent动网格【4】:DEFINE_CG_MOTION宏实例
    Fluent动网格【3】:DEFINE_CG_MOTION宏
    Fluent动网格【1】:概述
    Fluent动网格【2】:Profile文件
    JavaScript系列--浅析原型链与继承
    简单说说JavaScript的Generator 实现(ES6)
  • 原文地址:https://www.cnblogs.com/zhiying/p/5534487.html
Copyright © 2020-2023  润新知