js中没有必要为每一个对象实例创建类或者蓝图。可以在运行的时候创建它,同时你可以为对象添加任何的属性和方法。事实上在js中所有的对象都是一个关联数组。
var cc=new Object();
cc.firstName="sa";
cc.sayName=function () {
console.log(this.firstName);
};
cc["firstName"]="dd";
cc["sayName"](); //dd
创建对象
字面量的方式
var cc={
"aaa":"sas",
"author":{
"ll":"赵文娟",
"mm":"牛执行"
}
}
console.log(cc.author.mm);
关键字new
new关键字 +一个构造函数 (内置对象)
之所以js可以使用以上两种方式来创建对象,就是因为在js的内部是通过关联数组来实现对象的。
按属性访问和按键访问
按属性访问 对象.属性
按键访问 对象[属性]
可计算属性名
var prefix="sa";
var myObject={
[prefix+"1"]:"hello",
[prefix+"2"]:"wqwqq",
}
console.log(myObject["sa1"]);
但是在外部给数组添加非数字的属性的时候不会改变数组的长度
var arr=["foo",42];
arr["baz"]="sas";
console.log(arr.length); //2
加一个数字的属性的时候则会改变数组的长度
var arr=["foo",42];
arr["3"]="sas";
console.log(arr.length); //2
for(var i=0;i<arr.length;i++){
console.log(arr[i]); //中间会有一个undefined
}
对象的属性描述符:
以下这两个方法都是在ES5以后才可以使用的。
writable enumerable configurable
getOwnPropertyDescriptor得到了对象的描述符
var myObject={a:2}
//Object {value: 2, writable: true, enumerable: true, configurable: true}
console.log(Object.getOwnPropertyDescriptor(myObject,"a"));
myObject.a=10;
console.log(myObject.a);
设置对象的描述符
defineProperty()函数
var myObject={a:2}
//Object {value: 2, writable: true, enumerable: true, configurable: true}
Object.defineProperty(myObject,"a",{value:2,writable:false,configurable:false,enumerable:false});
myObject.a=10;
console.log(myObject.a); //2
虽然试图修改a的值,但是没有修改成功。但是非严格模式下不会报错。严格模式下则会报错。
对象禁止拓展
Object.preventExtensions()这个方法就可以禁止拓展
var myObject={a:2}
Object.preventExtensions(myObject);
myObject.b=3;
console.log(myObject.b); //undefined
对象的复制
json提供的一种巧妙地复制方法
var aa={a:1,cc:function () {
console.log(this.a);
}};
var b=JSON.parse(JSON.stringify(aa));
aa.cc(); //1
console.log(b.a);
b.a=3;
console.log(b.a);
b.cc(); //b.cc is not a function
运行到b.cc()会报错。说明这种方法是浅复制。
使用Object.assign()实现复制
var aa={a:1,cc:function () {
console.log(this.a);
}};
var b=Object.assign(aa);
aa.cc(); //1
console.log(b.a);
b.a=3;
console.log(b.a);
b.cc(); //3
Getter和Setter
getter是一个隐藏函数会在获取属性的时候调用,
setter也是一个隐藏函数,会在设置属性值时调用。
当给一个属性定义getter,setter的时候,js会忽略这个属性的value和writeable特性,取而代之的是比较关心getter和setter
var myobject={ get a(){return 2;}}
myobject.a=3;
Object.defineProperty(myobject,"b",{get:function () {
return this.a*2;
}})
myobject.a=20;
myobject.b=40;
console.log(myobject.a); //2
console.log(myobject.b); //4
同时如果在定义类的时候,如果只给a属性定义了get方法,那么所有的set操作都是没有意义的。所以一个即可以读取也可以修改的属性应该set和get方法都有。
var myobject={ get a(){return this._a_;},set a(a){this._a_=a}}
Object.defineProperty(myobject,"b",{get:function () {
return this.a*2;
}})
myobject.a=20;
myobject.b=40;
console.log(myobject.a); //20
console.log(myobject.b); //40
为什么b会被修改???
var myobject={ get a(){return this._a_;},set a(a){this._a_=a}}
Object.defineProperty(myobject,"b",{get:function () {
return 5;
}})
myobject.a=20;
myobject.b=40;
console.log(myobject.a); //20
console.log(myobject.b); //5
为什么又不能被修改了呢?
Object.create(xx.prototype)
就得到了xx的对象
属性的查询和设置
通过 . 号和 [] 和获取属性的值
对象可以看所是一个关联数组
但是值的注意的是 属性的名字最好不为数字。。
删除属性
delete 对象.属性
但是这个delete操作符只能删除自有 的属性,删除不了对象(类)从其他对象(类)继承来的属性
function inherit(p) {
if(p==null) throw TypeError();
if(Object.create) {
return Object.create(p);}
var t=typeof p;
if(t!="object"&&t!="function"){
function F() {
}
f.prototype=p;
return new F();
}
}
var o={};
o.x=1;
var p=inherit(o);
p.y=2;
var q=inherit(p);
q.cc=2;
console.log(q.cc); //2
delete q.cc;
console.log(q.cc); //undefined
console.log(q.x) //1
delete q.x;
console.log(q.x) //1
检测类中某个属性的存在
in 操作符
function inherit(p) {
if(p==null) throw TypeError();
if(Object.create) {
return Object.create(p);}
var t=typeof p;
if(t!="object"&&t!="function"){
function F() {
}
f.prototype=p;
return new F();
}
}
function A() {
this.x=1;
}
var a=new A();
var p=inherit(a);
p.y=2;
var q=inherit(p);
q.cc=2;
console.log("cc" in q) //true
console.log("x" in q) //true
console.log("y" in q) //true
delete q.cc;
console.log("cc" in q) //false
对象(类).hasOwnProperty(“属性”)
检测某个属性是否为对象或者类的自有属性(不是继承来的)。
function inherit(p) {
if(p==null) throw TypeError();
if(Object.create) {
return Object.create(p);}
var t=typeof p;
if(t!="object"&&t!="function"){
function F() {
}
f.prototype=p;
return new F();
}
}
function A() {
this.x=1;
}
var a=new A();
var p=inherit(a);
p.y=2;
var q=inherit(p);
q.cc=2;
console.log(q.hasOwnProperty("x")) //false
console.log(q.hasOwnProperty("cc")) //true
console.log(q.hasOwnProperty("y")) //false
对象.propertyIsEnumerable (属性)
这个属性既是自身的属性也是可枚举的,但是toString这个方法就不是可枚举 的
function inherit(p) {
if(p==null) throw TypeError();
if(Object.create) {
return Object.create(p);}
var t=typeof p;
if(t!="object"&&t!="function"){
function F() {
}
f.prototype=p;
return new F();
}
}
function A() {
this.x=1;
}
var a=new A();
var p=inherit(a);
p.y=2;
var q=inherit(p);
q.cc=2;
console.log(q.propertyIsEnumerable("x")) //false
console.log(q.propertyIsEnumerable("cc")) //true
console.log(q.propertyIsEnumerable("toString")) //false
属性的可枚举性
for in循环
两个数组的合并,并去掉重复的
var cc=[1,2,4,5,6];
var dd=[1,2,7,8];
function merge(p,q) {
for(var i in q){
if(q[i] in p) {
continue;
}
p.push(q[i]);
}
}
merge(dd,cc);
console.log(cc);
console.log(dd);
返回对象的所有的自有属性
var cc={x:1};
var dd=Object.create(cc);
dd.y=1;
console.log(Object.keys(dd)); //["y"]
console.log(Object.keys(cc)); //["x"]
遍历
for of 用法
var myArray=[1,2,3];
for(var v of myArray){
console.log(v);
}
但是这种方法是能访问数组。不能为普通的对象直接使用for of来访问,只有给普通对象定义了Symbol.iterator属性之后,才可以通过for v来访问
这个遍历的访问过程:首先循环会向被访问对象请求一个迭代器对象,然后通过调用迭代器对象的next()方法来遍历所有返回值。利用的就是数组内置的iterator。
Symbol.iterator这个属性是ES6新出来的,作用就是获取数组的@@iterator内部属性。
var myArray=[1,2,3];
var it=myArray[Symbol.iterator]();
console.log(it.next()); //Object {value: 1, done: false}
console.log(it.next()); //Object {value: 2, done: false}
console.log(it.next()); //Object {value: 3, done: false}
console.log(it.next()); //Object {value: undefined, done: false}
done表示的是是否还有可以遍历的值。
但是普通的对象没有内置的@@iterator属性。
var myObject={a:2,b:3};
var it=myObject[Symbol.iterator]();
console.log(it.next()); //myObject[Symbol.iterator] is not a function
Object.keys(myArray)这个方法是列出对象的所有的关键字。
var myArray={a:2,b:3};
console.log(Object.keys(myArray)); //["a","b"];
下面的这段代码实现的就是为普通的对象添加@@iterator属性
var myObject={a:2,b:3};
Object.defineProperty(myObject,Symbol.iterator,{
enumerable:false,
writable:false,
configable:true,
value:function () { //定义了Symbol.iterator的值 值里边主要是返回了一个函数next()
var o=this;
var idex=0;
var ks=Object.keys(o);
return {
next:function () { //返回的next是一个函数 这个函数里边返回了valu和done两个值
return{
value:o[ks[idex++]],
done:(idex>ks.length)
}
}
}
}
})
var it=myObject[Symbol.iterator]();
console.log(it.next()); //Object {value: 2, done: false}
console.log(it.next()); //Object {value: 3, done: false}
console.log(it.next()); //Object {value: undefined, done: true}
在定义Symbol.iterator了之后通过for v来遍历对象
var myObject={a:2,b:3};
Object.defineProperty(myObject,Symbol.iterator,{
enumerable:false,
writable:false,
configable:true,
value:function () { //定义了Symbol.iterator的值 值里边主要是返回了一个函数next()
var o=this;
var idex=0;
var ks=Object.keys(o);
return {
next:function () { //返回的next是一个函数 这个函数里边返回了valu和done两个值
return{
value:o[ks[idex++]],
done:(idex>ks.length)
}
}
}
}
})
for(v of myObject){
console.log(v); //2 3
}