zoukankan      html  css  js  c++  java
  • 浅析new关键字的作用

    假设说现在要构造若干个"士兵"对象 , 每个士兵都有类型 攻击力 生命值 这些属性
    同时有奔跑 攻击 防御 这些可以执行的动作 , 在代码中表现为方法

    简单粗暴的方式可以这样做

    var soldiers = [];
    for(let i=0 ; i<100 ; i++) {
    	let soldier = {
    		type : "步兵",
    		id : i,
    		health : 100,
    		run : function(){console.log("奔跑");},
    		attack : function(){console.log("攻击");},
    		defense : function(){console.log("防御");}
    	};
    	soldiers.push(soldier);
    }
    

    这种方式显然存在一个问题 , 就是浪费了大量的内存
    因为每个士兵可以执行的行为都是一样的 , 这几个函数完全可以共用
    这种方式却给每个对象创建了独立的函数
    兵种也是一样的 , 只有id和生命值 , 每个士兵都要具备自己的值

    可以给每个对象指定各自的原型对象 , 只要这些共用的方法写在原型对象当中

    var soldiers = [];
    var soldierProto = {
    	type : "步兵",
    	run : function(){console.log("奔跑")},
    	attack : function(){console.log("攻击");},
    	defense : function(){console.log("防御");}
    }
    for(let i=0 ; i<100 ; i++) {
    	let soldier = {
    		id : i,
    		health : 100
    	};
    	solider.__proto__ = soldierProto;
    	soldiers.push(soldier);
    }
    

    现在把创建士兵的代码放在了两个地方 , 很不优雅
    所以可以用一个函数把两者联系起来

    function createSoldier(id) {
    	var _soldier = {}; //临时对象
    	_soldier.__proto__ = createSoldier["原型"];
    	_soldier.id = id;
    	_soldier.health = 100;
    	return _soldier;
    }
    createSoldier["原型"]= {
    	type : "步兵",
    	attackNum : 5, //攻击力
    	run : function(){console.log("奔跑");},
    	attack : function(){console.log("攻击");},
    	defense : function(){console.log("防御");}
    }
    

    上面的代码在函数中添加了一个属性 , 叫做"原型"
    主要做的就是把需要作为原型的对象保存在函数对象的一个属性当中 , 使调用这个函数的时候可以获取到这个原型对象
    new关键字所做的事情 , 其实就相当于是上面代码里面我们自己手动实现的事情

    • 自动创建临时对象 ( 在函数内部使用this可以访问到这个临时对象 )
    • 自动绑定该Function对象的原型 ( 统一叫做prototype )
    • 自动return这个临时对象

    现在写一个可以用new去调用的纯粹的构造函数

    function soldier(id) {
    	this.id = id;
    	this.health = 100;
    }
    soldier.prototype = {
    	type : "步兵",
    	attackNum : 5, //攻击力
    	run : function(){console.log("奔跑");},
    	attack : function(){console.log("攻击");},
    	defense : function(){console.log("防御");}
    }
    

    除此之外 , 为了记录临时对象是由哪个函数创建的 , 会在定义这个函数的时候 , 在函数的prototype属性 ( 是Object ) 上面自动添加一个constructor属性 , 比如 :

    function func(){
    	this.name = "Sookie";
    }
    func.prototype.constructor === func; //true
    

    所以如果像上面那样直接给函数的prototype属性赋值一个对象的话 , 这个constructor就没了
    所以可以采取下面两种做法

    //1. 手工把这个属性加上
    soldier.prototype = {
    	constructor : soldier,
    	type : "步兵",
    	attackNum : 5, //攻击力
    	run : function(){console.log("奔跑");},
    	attack : function(){console.log("攻击");},
    	defense : function(){console.log("防御");}
    }
    

    或者

    //2. 不去覆盖原本的prototype属性对象, 而是直接在上面添加属性
    soldier.prototype.type = "步兵";
    soldier.prototype.attackNum = 5;
    soldier.prototype.run = function(){console.log("奔跑");};
    soldier.prototype.attack = function(){console.log("攻击");};
    soldier.prototype.defense = function(){console.log("防御");};
    
  • 相关阅读:
    组合算法问题
    递归之全排列问题
    递归之整数划分问题
    利用Python完成一个小游戏:随机挑选一个单词,并对其进行乱序,玩家要猜出原始单词
    对数组元素进行排序的方法总结(利用C++)
    用c++语言编写函数 int index(char *s,char * t),返回字符串t在字符串s中出现的最左边的位置,如果s中没有与t匹配的子串,则返回-1。类似于索引的功能。
    用MFC完成一个简单的猜数字游戏: 输入的四位数中,位置和数字都正确为A,数字相同而位置不同的为B。
    用Matlab完成:从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位。
    利用matlab实现以下功能:将一个正整数分解质因数。例如:输入90,打印出90=2*3*3*5。
    白书_倒三角形_C语言描述
  • 原文地址:https://www.cnblogs.com/programInit/p/6798343.html
Copyright © 2011-2022 走看看