js如何修改普通对象的原型(用以简单继承)

testUser7_7 发布于 11/06 15:26
阅读 84
收藏 0

js,让一个对象继承另一个对象的所有数据,不要逐个拷贝属性那种方法,不要创建function那种方法。

obj1 = { aa : 100 };
obj2 = { bb : 200 };

obj2.__proto__ = obj1;	// 让1作为2的原型

log(obj2.aa);	// 基类数据
log(obj2.bb);	// 自己的数据

上面的方法可以实现obj2继承obj1的数据,但是会提示"mutating prototype of an obj will cause code slowly",还有什么其他方法可以实现这种继承吗,不想用创建function那种复杂的方法,希望只是简单的加个原型链,像lua设置元表那样。

加载中
0
tcxu
tcxu

试试这麽写,是否还有提示?

<html>
<meta charset="utf-8">
<head>
<style>
#12{
}
</style>
</head>
<body><div id="12"></div>
</body>
<script>

var s=''; 
var obj1 = { aa : 100 };
var obj2 = { 
	bb : 200,
	__proto__: obj1 };

s += 'obj2 隐式继承 obj1:' + 'obj2.aa ' + obj2.aa + ',  obj2.bb: ' + obj2.bb;
document.write( s );  
</script>
</html>

楼主的案例,会有提示:"mutating prototype of an obj will cause code slowly 变换一个对象的原型,会造成代码运行慢"。
总所周知,js的函数对象和原型对象,分别通过 prototype 或 __proto__  显示或隐式地 进行相互关联(继承)。如果不通过函数对象的继承方式书写,就只有用  __proto__ 了。还有其它什么写法?

tcxu
tcxu
回复 @testUser7_7 : 通过字面量初始化的对象的唯一的默认属性 __proto__ 不是私有的(其实,js 没有访问修饰关键词),外界可以访问(读取、修改、赋值)它。 "手动修改__proto__",即在字面量初始化之后赋予新对象, 这种做法只能实现 "单继承",至于"隐患" 或 "常规写法" 的问题,我还没有答案。
tcxu
tcxu
回复 @testUser7_7 : 以下资料稍微解释为什么改变对象的 __proto__, 浏览器就运行慢:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/proto
t
testUser7_7
obj1和obj2的__proto__默认都指向同一个原型对象,现在我修改了obj2的__proto__,当通过obj2调用对象默认属性时,会到obj1里去找吧?会在obj1的__proto__里找到是吗
t
testUser7_7
多谢解答,为什么通过字面量形式初始化obj2时修改其原型不警告,而创建完obj2后再修改就提示警告。能不能理解为,__proto__是私有的,不希望被外界修改。还有,手动修改__proto__这种写法是不是常规写法,会有什么隐患吗,比如平台兼容性,或者影响对象的固有属性
0
tcxu
tcxu

诠释 js 的 __proto__ 
1. __proto__,是 对象(实体)。它 ( __proto__ ) 也有属性对象,一个 null(指空)的属性对象__proto__ 。
2. __proto__,是通过字面量初始化的对象的唯一的默认属性。 有人称它为'隐式原型',我看也可以把它叫做'准原型'。
3. prototype 是函数定义的原型。__proto__是它(prototype)的属性对象。如 1  所示,它( __proto__ ) 仅有一个属性对象(实体) 是一个null(指空)的引用(对象) __proto__ 。

<script>
function SuperType(){
    this.colors =['red', 'blue', 'green'];
}
s  = '函数原型(prototype)的属性__proto__是对象: ';
s += SuperType.prototype.__proto__;
s += '\n函数原型(prototype)的属性的属性__proto__是指空的对象: ';
s += SuperType.prototype.__proto__.__proto__;
alert(s);     
</script>


4.  通过字面量初始化的对象的唯一的默认属性 __proto__ 不是私有的(其实,js 没有访问修饰关键词),外界可以访问(读取、修改、赋值)它。 但是,在初始化之后,如楼主报告,外界只要'修改' 它 (比如,直接赋予其它类的引用),就会有“代码运行会慢”的 提示/警告。初始化后直接修改__proto__,  会影响性能,因为 “它还会影响到所有继承来自该 [[Prototype]] 的对象”。这样的行为是不推荐的。
5. 使用__proto__ , 是有争议的。原先,也不鼓励使用它。因为它过去没有被包括在 EcmaScript 语言规范中。然而,现代浏览器都实现了它。于是,__proto__属性 在 ECMAScript 6 语言规范中标准化了,用于确保 Web 浏览器的兼容性。

6. 通过字面量初始化的对象,可以实现 "双/多继承"。

<script>
var obj1 = {name : '王銘启', age : 28} //声明并用字面量初始化对象 obj1 
var obj2 = {position : '程序员', location: '天津' };//声明并用字面量初始化对象 obj2
var obj3 = {  };  //声明并用空字面量初始化对象 obj3 
	
for(var k in obj1){
    obj3.__proto__[k]=obj1[k];
}

for(var k in obj2){
    obj3.__proto__[k]=obj2[k];
}
s	='姓名:' + obj3.name + ',\t职位:' + obj3.position; 
s 	+='\n年龄:' + obj3.age + ',    \t工作地点:' + obj3.location ; 
alert(s); 
</script> 

7. 通过函数的原型,可以实现 "双/多继承"。

<script>
function Obj1(){
    this.age=26; 
	this.name="满汝陵";
	this.show1=function(){
		s = this.name + ', ' + this.age;
		return(s);
	}
}
function Obj2(){
    this.sex="男"; 
	this.position="测试员";
	this.show2=function(){
		s = this.sex + ', ' + this.position;
		return(s);
	}
}
function Obj3(){
	Obj1.call(this);
	Obj2.call(this);
	}

for(var k in Obj1.prototype){
    Obj3.prototype[k]=Obj1.prototype[k];
}
for(var k in Obj2.prototype){
    Obj3.prototype[k]=Obj2.prototype[k];
}

programer = new Obj3();
alert(programer.show1()+'\n'+programer.show2());  
</script>

8. 字面初始化对象的简单继承链。

<script>
var o1={age:26, name:"满汝陵" }; //对象的字面值
var o2={sex:"男", 
		position:"测试员",
		__proto__ : o1 
		};
var o3={compary:"武汉华视软件开发有限公司", 
		location:"武汉",
		__proto__ : o2,
		show : function(){
			s =  '继承链: \n';
			s += '姓名:' + this.name;
			s += ', 年龄:' + this.age;
			s += ', 性别:' + this.sex;
			s += ', 职称:' + this.position;
			s += '\n公司:' + this.compary;
			s += ' 地点:' + this.location;
			return s;
			}
		};
		
alert(o3.show());
</script>

参考:

Object.prototype.__proto__

 

t
testUser7_7
多谢解答
0
Kit_lee
Kit_lee

嗯,引用页上说得很清楚:直接修改__proto__,  之所以会影响性能,是因为“它还会影响到所有继承来自该 [[Prototype]] 的对象”。所以不管实际上代码有没有因此对性能造成很大的影响,反正这样的行为是不推荐的

返回顶部
顶部