array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 javascript object oriented programming (二) - 爱码网
  /*
	* 如何生成一个"继承"多个对象的实例。
	* 也就是说一个实例对象继承了多个对象的属性
	* 
	*	
  */
	function Animal(){
		this.species = '动物';
	}

	function Cat(name,color){
		this.name = name;
		this.color = color;
	}
	//1. 构造函数绑定
	//1.最简单的方法,大概就是使用call或apply方法,将父对象的构造函数绑定在子对象上,也就是在子对象构造函数中加一行
	function Cat(name,color){
		Animal.apply(this,arguments);      //将Animal构造函数绑定在了Cat对象上
		this.name = name;
		this.color = color;
	}
	var cat1 = new Cat('大黄','yellow');
	console.log(cat1.species);				//动物

	//2. prototype模式 更常见的做法,则是使用prototype属性。
	//如果"猫"的prototype对象,指向一个Animal的实例,那么所有"猫"的实例,就能继承Animal了。
		
	Cat.prototype = new Animal();    //Cat的prototype对象指向一个Animal的实例。
	Cat.prototype.constructor = Cat;
	var cat1 = new Cat('大黄','黄色');
	console.log(cat1.species);
	/*
	* 第二种方式的解释
	*任何一个prototype对象都有一个constructor属性,指向它的构造函数。
		也就是说,Cat.prototype 这个对象的constructor属性,是指向Cat的。
	*我们在前一步已经删除了这个prototype对象原来的值,所以新的prototype对象没有constructor属性,
		所以我们必须手动加上去,否则后面的"继承链"会出问题。这就是第二行的意思。
	* Cat.prototype = new Animal();		这里Cat.prototype对象的constructor的属性值,指向了Animal的实例,原本应该指向		Cat,也就是说已经删除了prototype对象constructor原来的值,所以新的prototype对象没有constructor属性(其实应该是有		constructor,但其值为Animal的实例对象,这是我的理解!),所以必须手动加上去,不然‘继承连’会出问题,
	* Cat.prototype.constructor = Cat;   //所以要把Cat.prototype.constructor的值指向原来的值
	*/
	//总之,这是很重要的一点,编程时务必要遵守。下文都遵循这一点,即如果替换了prototype对象,

      o.prototype = {}; //o的prototype的constructor设置为空了

	//那么,下一步必然是为新的prototype对象加上constructor属性,并将这个属性指回原来的构造函数。

      o.prototype.constructor = o;
	
	//3. 直接继承prototype
	//由于Animal对象中,不变的属性都可以直接写入Animal.prototype。所以,我们也可以让Cat()跳过 Animal(),
	//直接继承Animal.prototype。
	function Animal(){
		
	}

	function Cat(name,color){
		this.name = name;
		this.color = color;
	}
	Animal.prototype.species = '动物1';

	//将Cat的prototype对象,然后指向Animal的prototype对象,这样就完成了继承。
        Cat.prototype = Animal.prototype;
	//这一句实际上把Animal.prototype对象的constructor属性也改掉了!
        Cat.prototype.constructor = Cat;
		//console.log(Animal.prototype.constructor);   //Cat
        //console.log(Cat.prototype.constructor);		 //Cat
        var cat1 = new Cat("大黄","yellow");
        console.log(cat1.species);
	/*
		与前一种方法相比,这样做的优点是效率比较高(不用执行和建立Animal的实例了),比较省内存。缺点是 Cat.prototype和Animal.prototype现在指向了同一个对象,那么任何对Cat.prototype的修改,都会反映到Animal.prototype。
	*/
	 
	 //4. 利用空对象作为中介 (修复了上第3点方法直接继承的问题)
	//由于"直接继承prototype"存在上述的缺点,所以可以利用一个空对象作为中介。
	function Animal(){	
	}
	function Cat(name,color){
		
		this.name = name;
		this.color = color;
	}
	Animal.prototype.species = '动物';

	function F(){};
	//F是空对象,所以几乎不占内存。
	F.prototype = Animal.prototype;         
	Cat.prototype = new F();
	//这时,修改Cat的prototype对象的constructor属性,就不会影响到Animal的prototype对象的constructor属性。
	Cat.prototype.constructor = Cat;
	var cat1 = new Cat('大白','white');

    console.log(cat1.species);
	console.log(Cat.prototype.constructor);      //Cat  
	console.log(Animal.prototype.constructor);	 //Animal
	
	//5. prototype模式的封装函数
	//我们将上面的方法,封装成一个函数extend,便于使用。

	function Animal(){	
	}
	function Cat(name,color){
		
		this.name = name;
		this.color = color;
	}
	Animal.prototype.species = '动物';
	//这个extend函数,就是YUI库如何实现继承的方法。
	function extend(Child,Parent){
		var F= function(){};
		F.prototype = Parent.prototype;
		Child.prototype = new F();
		Child.prototype.constructor = Child;
	//意思是为子对象设一个spare属性,这个属性直接指向父对象的prototype属性。这等于是在子对象上打开一条通道,
	//可以直接调用父对象的方法。这一行放在这里,只是为了实现继承的完备性,纯属备用性质。
		Child.spare = Parent.prototype;
	}

	extend(Cat,Animal);
	var cat1 = new Cat("大黄","黄色");
	console.log(cat1.species)

	//6. 拷贝继承
	//上面是采用prototype对象,实现继承。我们也可以换一种思路,纯粹采用"拷贝"方法实现继承。简单说,如果把父对象的所有属性和方法,拷贝进子对象,不也能够实现继承吗?
	//首先,还是把Animal的所有不变属性,都放到它的prototype对象上。
	//我的理解就是把,如果拷贝的只是prototype对象的属性,就是把父对象原型上的属性拷贝到子对象的原型上。
	function copy_extend(Child,Parent){
		var c = Child.prototype;
		var p = Parent.prototype;
		for(var i in p){
			c[i] = p[i];
		}
		c.spare = p;
	}

	//consider following code
	function Animal(){	
	}
	function Cat(name,color){
		
		this.name = name;
		this.color = color;
	}
	Animal.prototype.species = '动物';
	Animal.prototype.method = '拷贝后的方法';
		function copy_extend(Child,Parent){
			var c = Child.prototype;
			var p = Parent.prototype;
			for(var i in p){
				c[i] = p[i];
			}
			c.spare = p;
		}

	copy_extend(Cat,Animal);
	var cat1 = new Cat("大黄","黄色");
	console.log(cat1.species);	//动物
	console.log(cat1.method);	//拷贝后的方法
	//个人认为,拷贝会增加memory的消耗。不如直接引用来的干脆。

/*
    *以上6种实现继承的方法的总结。
    *    Notice:1.每个构造函数内都有一个prototype属性,而这个prototype属性指向prototype对象,在mozilla里叫做__proto__
               2.没个prototype对象都有constructor属性,为了保持原来的原型链,每次改变值是要重新设置下。
    *构造函数:其实就是一个普通函数,但是内部使用了this变量。
                对构造函数使用new运算符,就能生成实例,并且this变量会绑定在实例对象上
    * <1 直接用call,apply引用方法,最简单。第一个参数是context上下文,第二参数是给引用方法的传入的参数。
    * <2 prototype模式,Animal函数内存在的方法,然后通过设置Animal的实例对象Cat的prototype.此时Cat上就有了Animal的
         属性了
    * <3 直接继承prototype,Cat.prototype = Animal.prototype, 然后实例化对象cat1就可以用Animal原型上的方法了。
         前提是Animal的方法在他的prototype对象上,但是Cat实例对象无法使用他构造函数内的属性和方法,除非在         
         Cat.prototype = new Animal(); 这样就引用了Animal函数内的属性和方法了,以及其prototype上的属性。
         这个方法的弊端就是相互引用后,改期任意一方的constructor属性,其他的一个也会改变。
      <4 利用空对象作为中介,可以弥补3的弊端。利用空对象F的prototype对象来引用Animal的prototype。然后将
         Cat.prototype = new F() 这样就可以使用Animal函数的方法了,然后重新设置下constructor属性.
         Cat.prototype.constructor = Cat Animal的prototype对象的constructor属性不会受影响。
      <5 将第4种方法封装为函数,之外,把子对象的属性引用了父对象的prototype对象 Chlid.spare = Parent.prototype
      <6 无非是把父对象中的所有属性和方法(包括父对象prototype上的所有属性)都拷贝到了子对象里,这样子对象也就可以使         用了。但这样完全没必要,耗memory!直接引用最方便。
    */

学习笔记,记录学习的过程。

原文链接:http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html

相关文章: