ssdasdasdasd
sdasdasds
创建对象的方式: var obj1={x:1,y:2};
var obj2 ={x:1,y:{a:2,b:3},z:4} 属性中还可以继续嵌套对象
用自变量创建的对象就有原型,指向Object.prototype
原型链: 每个对象obj都有一个proto标签,指向对象的原型链,原型链中的proto指向Object.prototype指向null
当对对象添加一个属性并赋值的时候,不会向对象的原型链查找,所以新属性别添加在对象中
如果要从元原型链上得到某个属性的属性值,可以用delete.obj.z删除对象上属性z
obj.z;再次查找属性z时,不在对象上,则会继续往原型链上找,找得到则返回,找不到则返回undefined
var obj = Object.create({x:1})(系统内置的函数,会接受一个对象的参数)让新创建的对象的原型指向参数
obj.x;//1
var obj=Object.create({x:1});
obj.x;//1
typeof obj.toString;//"function" //toString()来源Object源型链
obj.hasOwnProperty("x");//false
//原型链继承关系 :
obj->{x:1}->Object prototype ->null;
并不是所有对象都有toString()方法
var obj=Object.create(null);
obj.toString //undefined
此时原型链继承关系 :obj->null。所以无toString()方法
in 和 hasOwnProperty
in是判断该对象是否具有所要查找的属性
而hasOwnProperty则是判断该对象的实例是否具有所要查找的属性
因此可以自定义一个查找对象属性所在位置的函数:
function hasProperty(obj,property){
return obj.hasOwnProperty(property) && property in obj;
}//返回true时表示该属性在它的实例上,否则就在原型上
对象创建的三种方式
字面量创建对象
new 构造器的方式去创建(原型链):对象没有属性时会通过原型链向上查找,对象有属性不会通过原型链向上查找。给对赋值,不会修改prototype的值。通过原型链实现了继承原型上的属性。
Object.create()创建
Object.create创建对象传入一个参数
var obj = Object.create({x: 1}) 让obj这个对象的原型指向这个参数对象
参数对象的原型指向Object.prototype,所以可以拿到obj.toString
访问时会不断往原型链上查找属性值,但是修改的时候不会修改原型链上的值,如果在对象中直接找不到则会自动创建一个属性值在对象上,如下图
对象的原型链结构如下图,
'z' in obj 返回了true,表示z是属于这个对象的属性,但是它不是直接这个对象上的,而是obj原型链上的属性,所以使用obj.hasOwnProperty('z') 返回了false
[重点]Object.create方法
这里的箭头是[[proto]]的意思
注意下面的Object.create(null) 意思是 obj.__proto__ == null !
[重点] 函数 function(){} 的原型链
function XXX(){}
XXX.prototype.__proto__ === Object.prototype
Object.prototype.__proto__ = null
Object.create()
在proto原型上创建一个新的对象
.hasOwnProperty()
查找对象自身是否有指定的属性
原型链1111
给对象赋值的时候,不会向原型链去查找,仅在对象上添加或修改;
若需要拿到原型链上的z,则先需要delete对象上的z
z不是obj这个直接对象上的,而是对象的原型链上的
Object.create({x:1})创建一个对象,它的原型是{x:1}对象。
var obj=Object.create({x:1})创建的对象obj指向{x:1}。注意:属性x不属于obj!
出现的方法:
还可以通过Object.create方法来创建对象。
Object.create方法是一个系统内置函数,它通过接受一个参数一般是一个对象,创建一个新对象,并且让这个对象的原型指向这个参数。
用字面量创建的对象也是有原型的,指向Object.prototype,所以仍然可以用obj.toString方法。并且由于是从原型链上继承的而不是对象本身的属性,所以hasOwnProperty('x')会返回false。
并不是所有的对象都有toString,因为不一定所有对象的原型链上都有Object.prototype。所以如果用Object.create传入一个null,那么obj的原型直接就是null,这样它就不会包含任何方法。所以obj.toString返回undefined。
当我们给对象赋值的时候它不会在原型链上查找,也就是当给obj.z赋值的时候,先看obj.z有没有,如果有的话修改它的值,如果没有的话仅在这个对象上添加这个z=5。
这时,obj.hasOwnProperty('z')为true,因为obj上有z了;而foo.prototype.z仍为3,证明这个值没有被修改;而obj.z会返回5。
如果给z赋值为undefined的话,那么访问obj.z就为undefined,这个值还是有的,只是值被改为了undefined。
所以obj.z为undefined不一定是obj上没有z属性,也可能是它的值被赋为了undefined。这时可以通过hasOwnProperty或者in操作符来区分。
如果想再拿到原型上的z,那么需要先delete obj.z,然后再去访问obj.z,这样对象上的属性就会被删除,拿到的就是foo.prototype.z。
如果继续尝试delete obj.z,因为delete只能删除掉这个对象上的属性而不会影响到它的原型链。这样就实现了继承,通过这个继承我们可以继承原型链上的属性,反过来我们又不会修改它。
1、创建函数foo(),每个函数都有一个prototype属性。
2、先给foo.prototype属性添加一个属性z赋值3。每个对象都有一个proto标签。
3、通过new foo()构造器的方式构造一个新对象obj,再给它添加属性x=1、y=2。通过构造器的方式创建的对象,它的原型会指向构造器的prototype属性,也就是foo.prototype。
4、foo.prototype也有原型,它的原型是Object.prototype,Object.prototype的原型是null。
5、toString方法是Object.prototype上的。
6、因为z属性是obj从foo.prototype上继承来的,所以'z' in obj返回true;而obj.hasOwnProperty('z')返回false,证明z不是obj这个对象上的,而是它所在的原型链上的。
可以通过字面量创建对象。对象字面量也可以做嵌套,比如某个属性的值可以又是对象,通过花括号来继续嵌套下去
创建对象 var obj ={}
var f = new Foo();
Object.create({x:1});
函数默认有prototype对象
new一个函数对象,对象的proto指向函数的prototype
函数的prototype指向Object.prototype
‘z’in obj; // true z是原型上的
obj.hasOwnProperty('z') // false z 不是obj对象上的
通过Object.create创建对象
原型链上的delete 只会删除对象上的属性 ,不会影响到原型链