js对象深拷贝和对象扩展
2014-03-17 11:38
288 查看
原文:http://pouyang.javaeye.com/blog/576127
JavaScript中的对象是可变的键控集合(keyed collections)
对象是属性的容器,其中每个属性都拥有名字和值。属性的名字可以是
包括字符串在内的任意字符串,属性值可以是除undefined值之外的任何值
JavaScript中的对象是无类别的,它对新属性的名字和值没有约束。对象适合
用于收集和管理数据。对象可以包含其他对象,所以它们可以容易地表示成
树形或图形结构(注意:树和图强大的数据结构)
JavaScript包括一个原型链特性,允许对象继承另一对象的属性。正确地使用它能
减少对象初始化的时间和内存消耗
对象检索
Js代码
var
empty_object = {};
var
stooge = {
"first-name"
: "Ouyang"
,
"last-name"
: "ping"
,
"yyl"
: "yyl"
}
alert(stooge[ "first-name"
]); //Ouyang
alert(stooge.first-name); //NaN
alert(stooge.yyl) //yyl
alert(stooge.name); //undefined
||运算符可以用来填充默认值
Js代码
var middle = stooge["middle-name"] ||"none";
flight.equipment // undefined
flight.equipment.model // throw "TypeError"
flight.equipment && flight.equipment.model //undefined
原型
返回对象类型原型的引用。
objectName.prototype
objectName 参数是对象的名称
原型连接在更新时是不起作用的,当我们对某个对象做出改变时,不会触及到该对象
的原型,原型连接只有在检索值的时候才被用到,如果我们尝试去获取对象的某个属性,且
该对象没有此属性,那么JavaScript会试着从原型对象中获取属性值。如果那个原型对象也
没有该属性,那么再从它的原型中寻找,依次类推,直到该过程最后到达
终点Object.prototype,如果想要的属性完全不存在于原型链中,那么结果就是
undefied值,这个过程成为委托。
Js代码
function TestObjectA()
{
this.MethodA = function()
{
alert('TestObjectA.MethodA()');
}
}
function TestObjectB()
{
this.bb = 'ccc';
this.MethodB = function()
{
alert('TestObjectB.MethodB()');
}
}
TestObjectB.prototype = new TestObjectA(); //TestObjectB继承了 TestObjectA的方法
TestObjectB.prototype.bb = 'aaaaa'; //添加属性
var temp
var b = new TestObjectB();
for (temp in b) {
alert(temp); // MethodA bb MehtedB
}
var kk = new TestObjectB();
//删除,但原型链中的没有删除
alert(kk.bb); // ccc
delete kk.bb;
alert(kk.bb); // aaaa
alert(kk.MethodA()); //TestObjectA.MethodA()
此处转载 http://fengsky491.javaeye.com/blog/228583 谢谢 fengsky491
JScript里的prototype,为什么我们说它和prototype pattern里的prototype不一样呢?! 这个不是我说就说出来的,也不是我吹出来的,看看这个示例,你就能大概糊涂:
Js代码
<script language="javascript">
function RP()
{
RP.PropertyA = 1;
RP.MethodA = function()
{
alert("RP.MethodA ");
};
this.PropertyA = 100;
this.MethodA = function()
{
alert("this.MethodA");
};
}
RP.prototype.PropertyA = 10;
RP.prototype.MethodA = function()
{
alert("RP.prototype.MethodA");
};
</script>
不要着急,还没有开始做示例,只是给出了我们用来演示的一个类。RP是什么?rpwt吗?当然不是了,RP是ResearchPrototype了。好了不废话了,看示例及结果分析。
Js代码
<script language="javascript">
rp = new RP();
alert(RP.PropertyA);
RP.MethodA();
alert(rp.PropertyA);
rp.MethodA();
</script>
运行结果闪亮登场:
1
RP.MethodA
100
this.MethodA
这个%$@#^$%&^...,不要着急,继续看哦!
Js代码
<script language="javascript">
rp = new RP();
delete RP.PropertyA;
alert(RP.PropertyA);
delete RP.MethodA;
RP.MethodA();
delete rp.PropertyA;
alert(rp.PropertyA);
delete rp.MethodA;
rp.MethodA();
</script>
运行结果再次登场:
undefined
A Runtime Error has occurred.
Do you wish to Debug?
Line: 32
Error: Object doesn't support this property or method
10
RP.prototype.MethodA
好玩吧,看出来什么名堂了吗?这里的RP.PropertyA和RP.MethodA只是用来做参照的,可是怎么把this.PropertyA和this.MethodA都delete了,还能出来结果,而且还是prototype导入的属性和方法呢?
这就是JScript的prototype和prototype pattern中prototype最大的不同了,JScript中的这个所谓的prototype属性其实是个语言本身支持的特性,这里没有发生任何的copy,不管shallow还是deep的。对于JScript的解释引擎,它在处理"."或"[keyName]"引用的对象的属性和方法时,先在对象本身的实例(this)中查找,如果找到就返回或执行。如果没有查找到,就查找对象的prototype(this.constructor.prototype)里是否定义了被查找的对象和方法,如果找到就返回或执行,如果没有查找到,就返回undefined(对于属性)或runtime
error(对于方法)。
正因为prototype导入类实例的属性或方法是动态查找的,所以我们才能对系统内部对象添加prototype属性和方法,比如给String对象添加trim方法:
Js代码
<script lanuage="javascript">
String.prototype.trim()
{
return this.replace(/(^\s+)|(\s+$)/g, "");
}
</scritp>
显然JScript中的这种用法也是prototype pattern中的prototype不能解释和支持的。
这下对于JScript OOP中原型继承法的理解因该没有任何的障碍了吧?同时也应该明白为什么原型继承法有那么大的天生缺陷了吧?当然如果有任何问题,欢迎继续讨论。
反射
检查对象并确定对象有什么属性是很容易的事情,只要试着去检索
该属性并验证取得的值,typeof操作符对确定属性的类型很有帮助。
Js代码
typeof flight.number
另一个方法是使用hasOwnProperty方法,如果对象拥有独有的属性,它将返回true.
hasOwnProperty方法不会检查原型连
Js代码
flight.hasOwnProperty('nubmer');
枚举(对象属性)
for in 语句可用来遍历一个对象中的所有属性名,该枚举过程将会列出所有的属性
包括函数和你可能不关心的原型中的属性,所以有必要过滤掉那些你不想要的值。最为常用
的过滤器是hasOwnProperty方法,以及使用typeof来排除函数:
Js代码
var name;
for (name in another_stooge) {
if (typeof another_stooge[name] != 'function') {
document.writeln(name+':'+another_stooge[name]);
}
}
属性名出现的顺序是不确定的,因此要对任何可能出现的顺序有所准备,如果你想要确保属性以特定的顺序出现,
最好的办法就是完全避免使用 for in语句,而是创建一个数组,在其中以正确的顺序包含属性名
Js代码
var i ;
var properties = [
'first-name',
'middle-name',
'last-name',
'profession'
];
for (i = 0 ; i < properties.length; i += 1) {
document.writeln(properties[i]+':'+another_stooge[properties[i]]);
}
通过使用for而不是for in ,可以得到我们想要的属性,而不用担心可能发掘出原型链中的属性,并且我们按
正确的顺序取得了它们的值。
http://www.blogjava.net/jasmine214--love/archive/2010/06/27/324606.html
JavaScript中的对象是可变的键控集合(keyed collections)
对象是属性的容器,其中每个属性都拥有名字和值。属性的名字可以是
包括字符串在内的任意字符串,属性值可以是除undefined值之外的任何值
JavaScript中的对象是无类别的,它对新属性的名字和值没有约束。对象适合
用于收集和管理数据。对象可以包含其他对象,所以它们可以容易地表示成
树形或图形结构(注意:树和图强大的数据结构)
JavaScript包括一个原型链特性,允许对象继承另一对象的属性。正确地使用它能
减少对象初始化的时间和内存消耗
对象检索
Js代码
var
empty_object = {};
var
stooge = {
"first-name"
: "Ouyang"
,
"last-name"
: "ping"
,
"yyl"
: "yyl"
}
alert(stooge[ "first-name"
]); //Ouyang
alert(stooge.first-name); //NaN
alert(stooge.yyl) //yyl
alert(stooge.name); //undefined
var empty_object = {}; var stooge = { "first-name":"Ouyang", "last-name":"ping", "yyl":"yyl" } alert(stooge["first-name"]); //Ouyang alert(stooge.first-name);//NaN alert(stooge.yyl)//yyl alert(stooge.name);//undefined
||运算符可以用来填充默认值
Js代码
var middle = stooge["middle-name"] ||"none";
flight.equipment // undefined
flight.equipment.model // throw "TypeError"
flight.equipment && flight.equipment.model //undefined
var middle = stooge["middle-name"] ||"none"; flight.equipment // undefined flight.equipment.model 4000 // throw "TypeError" flight.equipment && flight.equipment.model //undefined
原型
返回对象类型原型的引用。
objectName.prototype
objectName 参数是对象的名称
原型连接在更新时是不起作用的,当我们对某个对象做出改变时,不会触及到该对象
的原型,原型连接只有在检索值的时候才被用到,如果我们尝试去获取对象的某个属性,且
该对象没有此属性,那么JavaScript会试着从原型对象中获取属性值。如果那个原型对象也
没有该属性,那么再从它的原型中寻找,依次类推,直到该过程最后到达
终点Object.prototype,如果想要的属性完全不存在于原型链中,那么结果就是
undefied值,这个过程成为委托。
Js代码
function TestObjectA()
{
this.MethodA = function()
{
alert('TestObjectA.MethodA()');
}
}
function TestObjectB()
{
this.bb = 'ccc';
this.MethodB = function()
{
alert('TestObjectB.MethodB()');
}
}
TestObjectB.prototype = new TestObjectA(); //TestObjectB继承了 TestObjectA的方法
TestObjectB.prototype.bb = 'aaaaa'; //添加属性
var temp
var b = new TestObjectB();
for (temp in b) {
alert(temp); // MethodA bb MehtedB
}
var kk = new TestObjectB();
//删除,但原型链中的没有删除
alert(kk.bb); // ccc
delete kk.bb;
alert(kk.bb); // aaaa
alert(kk.MethodA()); //TestObjectA.MethodA()
function TestObjectA() { this.MethodA = function() { alert('TestObjectA.MethodA()'); } } function TestObjectB() { this.bb = 'ccc'; this.MethodB = function() { alert('TestObjectB.MethodB()'); } } TestObjectB.prototype = new TestObjectA(); //TestObjectB继承了 TestObjectA的方法 TestObjectB.prototype.bb = 'aaaaa'; //添加属性 var temp var b = new TestObjectB(); for (temp in b) { alert(temp); // MethodA bb MehtedB } var kk = new TestObjectB(); //删除,但原型链中的没有删除 alert(kk.bb); // ccc delete kk.bb; alert(kk.bb); // aaaa alert(kk.MethodA()); //TestObjectA.MethodA()
此处转载 http://fengsky491.javaeye.com/blog/228583 谢谢 fengsky491
JScript里的prototype,为什么我们说它和prototype pattern里的prototype不一样呢?! 这个不是我说就说出来的,也不是我吹出来的,看看这个示例,你就能大概糊涂:
Js代码
<script language="javascript">
function RP()
{
RP.PropertyA = 1;
RP.MethodA = function()
{
alert("RP.MethodA ");
};
this.PropertyA = 100;
this.MethodA = function()
{
alert("this.MethodA");
};
}
RP.prototype.PropertyA = 10;
RP.prototype.MethodA = function()
{
alert("RP.prototype.MethodA");
};
</script>
<script language="javascript"> function RP() { RP.PropertyA = 1; RP.MethodA = function() { alert("RP.MethodA "); }; this.PropertyA = 100; this.MethodA = function() { alert("this.MethodA"); }; } RP.prototype.PropertyA = 10; RP.prototype.MethodA = function() { alert("RP.prototype.MethodA"); }; </script>
不要着急,还没有开始做示例,只是给出了我们用来演示的一个类。RP是什么?rpwt吗?当然不是了,RP是ResearchPrototype了。好了不废话了,看示例及结果分析。
Js代码
<script language="javascript">
rp = new RP();
alert(RP.PropertyA);
RP.MethodA();
alert(rp.PropertyA);
rp.MethodA();
</script>
运行结果闪亮登场:
1
RP.MethodA
100
this.MethodA
这个%$@#^$%&^...,不要着急,继续看哦!
<script language="javascript"> rp = new RP(); alert(RP.PropertyA); RP.MethodA(); alert(rp.PropertyA); rp.MethodA(); </script> 运行结果闪亮登场: 1 RP.MethodA 100 this.MethodA 这个%$@#^$%&^...,不要着急,继续看哦!
Js代码
<script language="javascript">
rp = new RP();
delete RP.PropertyA;
alert(RP.PropertyA);
delete RP.MethodA;
RP.MethodA();
delete rp.PropertyA;
alert(rp.PropertyA);
delete rp.MethodA;
rp.MethodA();
</script>
运行结果再次登场:
undefined
A Runtime Error has occurred.
Do you wish to Debug?
Line: 32
Error: Object doesn't support this property or method
10
RP.prototype.MethodA
<script language="javascript"> rp = new RP(); delete RP.PropertyA; alert(RP.PropertyA); delete RP.MethodA; RP.MethodA(); delete rp.PropertyA; alert(rp.PropertyA); delete rp.MethodA; rp.MethodA(); </script> 运行结果再次登场: undefined A Runtime Error has occurred. Do you wish to Debug? Line: 32 Error: Object doesn't support this property or method 10 RP.prototype.MethodA
好玩吧,看出来什么名堂了吗?这里的RP.PropertyA和RP.MethodA只是用来做参照的,可是怎么把this.PropertyA和this.MethodA都delete了,还能出来结果,而且还是prototype导入的属性和方法呢?
这就是JScript的prototype和prototype pattern中prototype最大的不同了,JScript中的这个所谓的prototype属性其实是个语言本身支持的特性,这里没有发生任何的copy,不管shallow还是deep的。对于JScript的解释引擎,它在处理"."或"[keyName]"引用的对象的属性和方法时,先在对象本身的实例(this)中查找,如果找到就返回或执行。如果没有查找到,就查找对象的prototype(this.constructor.prototype)里是否定义了被查找的对象和方法,如果找到就返回或执行,如果没有查找到,就返回undefined(对于属性)或runtime
error(对于方法)。
正因为prototype导入类实例的属性或方法是动态查找的,所以我们才能对系统内部对象添加prototype属性和方法,比如给String对象添加trim方法:
Js代码
<script lanuage="javascript">
String.prototype.trim()
{
return this.replace(/(^\s+)|(\s+$)/g, "");
}
</scritp>
<script lanuage="javascript"> String.prototype.trim() { return this.replace(/(^\s+)|(\s+$)/g, ""); } </scritp>
显然JScript中的这种用法也是prototype pattern中的prototype不能解释和支持的。
这下对于JScript OOP中原型继承法的理解因该没有任何的障碍了吧?同时也应该明白为什么原型继承法有那么大的天生缺陷了吧?当然如果有任何问题,欢迎继续讨论。
反射
检查对象并确定对象有什么属性是很容易的事情,只要试着去检索
该属性并验证取得的值,typeof操作符对确定属性的类型很有帮助。
Js代码
typeof flight.number
typeof flight.number b635
另一个方法是使用hasOwnProperty方法,如果对象拥有独有的属性,它将返回true.
hasOwnProperty方法不会检查原型连
Js代码
flight.hasOwnProperty('nubmer');
flight.hasOwnProperty('nubmer');
枚举(对象属性)
for in 语句可用来遍历一个对象中的所有属性名,该枚举过程将会列出所有的属性
包括函数和你可能不关心的原型中的属性,所以有必要过滤掉那些你不想要的值。最为常用
的过滤器是hasOwnProperty方法,以及使用typeof来排除函数:
Js代码
var name;
for (name in another_stooge) {
if (typeof another_stooge[name] != 'function') {
document.writeln(name+':'+another_stooge[name]);
}
}
var name; for (name in another_stooge) { if (typeof another_stooge[name] != 'function') { document.writeln(name+':'+another_stooge[name]); } }
属性名出现的顺序是不确定的,因此要对任何可能出现的顺序有所准备,如果你想要确保属性以特定的顺序出现,
最好的办法就是完全避免使用 for in语句,而是创建一个数组,在其中以正确的顺序包含属性名
Js代码
var i ;
var properties = [
'first-name',
'middle-name',
'last-name',
'profession'
];
for (i = 0 ; i < properties.length; i += 1) {
document.writeln(properties[i]+':'+another_stooge[properties[i]]);
}
var i ; var properties = [ 'first-name', 'middle-name', 'last-name', 'profession' ]; for (i = 0 ; i < properties.length; i += 1) { document.writeln(properties[i]+':'+another_stooge[properties[i]]); }
通过使用for而不是for in ,可以得到我们想要的属性,而不用担心可能发掘出原型链中的属性,并且我们按
正确的顺序取得了它们的值。
http://www.blogjava.net/jasmine214--love/archive/2010/06/27/324606.html
相关文章推荐
- JS中常用操作技巧(页面动态增加div,contain方法扩展,JSON对象鱼字符串转换)
- js实现的对象深拷贝
- Arcgis for JS扩展GraphicLayer实现区域对象的聚类统计与展示
- JS中禁止对象属性扩展、密封对象、冻结对象
- 使用prototype扩展JS内部对象String的功能
- 详解js中对象的深浅拷贝
- JS中Array对象扩展(一)
- js 对象的深拷贝
- js实现复制对象、扩展对象 方法
- JS日期对象扩展-日期格式化
- JS中禁止对象属性扩展、密封对象、冻结对象
- js扩展Date对象 日期格式化
- JS中深拷贝数组、对象、对象数组方法总结
- [js高手之路] es6系列教程 - 对象功能扩展详解
- js对象或json对象深拷贝
- webkit的js对象扩展(一)——binding方式创建自定义对象(单实例)
- android 上 webkit js 扩展之全局本地对象实现步骤
- js-ES6学习笔记-对象的扩展
- 详解JS中Array对象扩展与String对象扩展
- JS中禁止对象属性扩展、密封对象、冻结对象