1.对象
万物皆对象,对象是一个具体的对象。
对象是一组无序的相关属性和方法的集合。
属性:对象的特征(名词); 方法:对象的行为(动词)。
字符串,布尔,数值也为对象,也是通过对象方法创建的,也可以去调用对象的原始方法toString. (是通过原型链进行调用的,null和undefined不能调用对象原始方法)
创建字符串 var str = ‘xiaoming’; str.toString();//因为调用时,js会自动进行装箱操作 String(‘str’) toString() 再进行拆箱 str
2.创建对象
2.1 字面量方式创建对象
var obj={ }; //创建了一个空对象
var obj={
属性名:属性值, //属性
方法名:匿名函数, //方法
...
}
创建的对象的属性和方法采用键值对的方式,多个属性和方法之间用逗号隔开。
var stu ={
name:'xiaoming', //属性
weigth:60,
heigth:180,
cook(){ //方法
console.log(this.name+'去做饭')
},
housework(){
console.log('去做家务')
},
}
2.2 使用new 创建对象
var obj=new Object( ); //创建一个空对象 obj.name=‘xiaoming’; //属性 obj.age=19; obj.sex=‘男’; obj.sayHi =function(){ //方法 console.log(‘hi’); }
利用等号赋值,添加对象的属性和方法 属性方法之间用分号隔开,以分号结束。
3.使用对象
3.1 调用对象的属性:
- 对象名 . 属性名
- 对象名[’ 属性名 ']
3.2 调用对象的方法:
- 对象名 . 方法名()
console.log(stu.name); console.log(stu[‘name’]); stu.cook();
3.3删除对象的属性
只能删除自定义属性,无法删除继承属性 delete stu.weigth;
3.4新增属性并赋值
若原对象没有改属性,则为新增,若有该属性,则修改值 stu.weigth=‘80’;
3.5遍历对象属性 for…in
for…in通常用来遍历对象属性。 能被for…in语句打印的属性称为可枚举属性,默认情况下自定义属性都是可以被枚举的。
for(var k in stu){
console.log(k); //对象属性的键(属性名)
}
for(var k in stu){
console.log(stu[k]); //对象属性的值
}
对象转为布尔类型时,当对象为空,则转为false,其他情况为true
3.6变量,属性,函数,方法的区别
- 变量和属性
同:都是用来存储数据的; 异:变量需要单独声明并赋值,使用时直接写变量名,单独存在;属性在对象中不需要声明,使用时必须为 对象名.属性,依赖于对象。 - 函数和方法
同:都是实现某种功能; 异:函数时单独声明,并且调用时 函数名(),单独存在;方法是在对象里的,调用时需要 对象名.方法名(),依赖于对象。
4.构造函数
因为我们每次创建不同对象中的很多属性和方法大多是相同的,我们可以利用函数的方法重复这些相同的代码,把这个函数称为构造函数。
构造函数和普通函数不同,里面封装的不是普通代码,而是对象。
构造函数就是把对象里的一些相同的属性和方法抽象出来封装到函数里。
4.1创建构造函数
function 构造函数名(){
this . 属性 = 值;
this . 方法 = function( ) { }
}
new 构造函数名();
构造函数名首字母需要大写。 构造函数不需要return就可以返回结果。 调用构造函数必须使用new。 只要调用函数就创建了一个对象。 属性和方法前必须添加this。
//构造函数(泛指某一类事物)
function Star( name,age,sex ){
this.name=name;
this.age=age;
this.sex=sex;
this.sing = function( sang ){
console.log(sang);
}
}
//对象(具体的某个事物)
var ldh = new Star(‘刘德华’ ,18,‘男’); //调用函数,返回的是一个对象
var zxy = new Star('张学友' , 19 , '男') ;
console.log(ldh.name);
console.log(ldh[ 'sex' ]);
ldh.sing('冰雨');
使用构造函数创建对象的过程也称对象实例化。
4.2 new关键字
- 遇到new 构造函数在内存中创建一个空的对象;
- this指向创建的空对象;
- 执行构造函数中的代码,给空对象添加属性和方法;
- 返回这个对象。
对象类型转换
var obj ={ } console.log(Boolean(obj)); console.log(obj.toString()); console.log(String(obj));
重写一个对象的toString var obj={ name:‘xiaoming’, toString:function(){ return ‘is’+this.name } } console.log(obj.toString()); // isxiaoming console.log(String(obj)); //重写tostring()时,使用String包装器时,先调用tostring()中的值,再进行包装
valueOf和toString的区别 1.这两个方法都是对象的原始方法 2.valueOf为对象的原始值,通常不会显示的调用,通常由js自动在后台进行调用 3.toString本身的一个作用是字符串的转换,也会进行自动转换 4.若重写了这两个方法,运算时,优先调用valueOf,在进行显示时,优先调用toString 5.若只重写了一个方法,在运算和显示时,都优先调用该方法 var obj={ num:1, toString:function(){ return this.num+1; }, valueOf:function(){ return this.num+2; } } //因为num在valueOf中被引用,所以不会被垃圾回收机制回收 console.log(obj==2);//3 运算时应该调用valueOf() //alert(obj);//2 浏览器弹窗
var obj={ num:1, toString:function(){ return this.num+1; }, valueOf:function(){ return this.num++; } } console.log(obj1); //比较运算调用valueOf() 第一次调用 1++ console.log(obj2); // 每次调用obj时,都执行一遍valueOf() 2++ console.log(obj==3); // 3++ 如果没有重写valueOf,那么转为数值类型时返回NaN,如果重写则优先调用valueOf console.log(Number(obj)); //4
在对象中的检测属性和方法 in 关键词 检测某个属性是否是某个属性的自有属性或继承属性(可以使用的属性) **hasOwnProperty(propertyName)**检测某个属性是否是某个对象的自有属性,不能是继承的属性 propertyIsEnumerable() 检测某个属性是否是某个对象的自有属性且可以枚举的属性 var obj={ name:‘xiaoming’ } console.log(‘toString’ in obj); //true toString为对象的原始属性 console.log(‘name’ in obj); // true name 为obj的属性 console.log(‘aaa’ in obj); // false console.log(obj.hasOwnProperty(‘toString’)); //false toString为继承属性 console.log(obj.hasOwnProperty(‘name’)); //true name为继承属性 console.log(obj.propertyIsEnumerable(‘toString’)); //false 不是可枚举属性
检测是否在同一个原型链中(家族) 顶层对象包括属性和方法 isPrototyprOf测试一个对象是否存在于另一个对象的原型链上(原型的指向) instanceof 检测一个对象是否是这个构造函数的实例 (对象是否由某个对象函数创建)
function Animal () {} var dog1 =new Animal(); //instanceof 检测一个对象是否是这个构造函数的实例 (对象是否由某个对象函数创建) console.log(dog1 instanceof Animal); //true dog1为构造函数Animal的一个实例 console.log(dog1 instanceof Object); //true 所有对象(自定义或继承)的顶层都为object //isPrototypeOf测试一个对象是否存在于另一个对象的原型链上(原型的指向) console.log(Animal.prototype.isPrototypeOf(d1)); //检测 d1是否在Animal的原型链上
var obj={}; console.log(Object.prototype.isPrototypeOf(obj)); function Dog(){} Dog.prototype=new Animal();//原型链继承(将子类的构造函数的原型属性指向父类的实例) var d2=new Dog(); //d2同时拥有Animal,Dog和Object的方法和属性 console.log(Animal.prototype.isPrototypeOf(d2));
设置一个对象的原始属性
var obj={
name:'xiaoming',
age:12,
sex:'男'
}
Object.defineProperty(obj,'name',{ //修改name属性的原始属性
configurable:false, //不能被删除
enumerable:false, //不可枚举
writable:false, //不能修改
value:'lisi' //值改为'lisi'
})
console.log(obj) //不能枚举 {age:12,sex:'男'}
console.log(obj.name) //可以调用 lisi
obj.name='xiaoming'; //设置name原始属性不可修改,修改失败
delete obj.name; //设置为不可删除属性,删除失败
console.log(obj.name); //lisi
for(var k in obj){
console.log(obj[k]);
} //设置name为不可枚举 12 男
Object.getOwnProperityDescriptor() 显示某个属性的原始属性
var res=Object.getOwnPropertyDescriptor(obj,'name');
console.log(res);
一次设置对象多个属性的原始属性 Object.definePropertys
Object.definePropertys(obj,{
age:{
configurable:false
},
sex:{
configurable:false
}
})
构造器属性 在对象中,我们可能会设置一些比较奇怪的属性_num,这种属性我们称为构造器属性 这种属性一般不希望直接通过外部访问(obj._num) 我们希望自己去控制这个属性的访问逻辑, obj.num可以访问到,然后对它进行一些逻辑改变 构造器属性可以重写自定义属性的get和set方法
var obj={ _num:0 } obj.num可以访问到,返回 数字:0 Object.defineProperty(obj,‘num’,{ //当我们没有设置这个属性时,默认是隐式调用,如果设置了,会调用你设置的方法 //重写自定义属性的set和get属性 set(num){ thsi._num=num }, //在num的值被设置时调用 get(){ return ‘数字:’+this._num }//在num的值被获取时,调用 }) console.log(obj.num); obj.num=5; console.log(obj.num);
序列化和反序列化 JSON.Stringify();//系列化 JSON.parse(); //反序列化
当基本数据类型调用原型方法时,实际JS完成了装箱(转换成对应类型的对象)和拆箱(把对象还原为原来的数据类型)的过程 var num1=123; //数值类型 var num2=Number(123); //数值类型 var num3=new Number(123); //对象类型 console.log(num1); console.log(num2); console.log(num3);
var str1=String(‘xiaobai’); var str2=new String(‘xiaohei’); console.log(str1); console.log(str2);
function Animal(name){ return name; } var dog1=Animal(‘xiaobai’); var dog2=new Animal(‘xiaohei’); console.log(dog1); console.log(dog2);
类型 console.log(typeof num2 ) //number console.log(typeof num3) //object console.log(num3.valueOf()= =num1); console.log(num3===num2);
js创建对象的方式 工厂模式 function Dog(name,age){ var obj=new Object(); obj.name=name; obj.age=age; return obj; } var first=Dog(‘xioabai’,1); var second=Dog(‘xiaohei’,2); console.log(first); console.log(second);
构造函数方式创建对象 function Animal(name,age){ this.name=name; this.age=age; /* this.sayName=function(){ console.log(this.name); }每一次创建函数时都会去创建一个新的函数*/ this.sayName=sayName; } //可以把函数写在全局,可以避免重复创建函数的尴尬 //但是这么使用封装性较差 function sayName(){ console.log(this.name); }
var dog1=new Animal(‘xiaobai’,2); var dog2=new Animal(‘xiaohei’,1); console.log(dog1); console.log(dog2); dog2.sayName();
//原型模式 function Dog() {} 在prototype中定义的属性和方法,所有的实例对象都共享 Dog.prototype.name=‘xiaobai’; Dog.prototype.age=2; Dog.prototype.text={ //在原型模式创建时,如果属性是引用数据类型,可能会 t:‘is dog’ }; Dog.prototype.sayName=function(){ console.log(this.name); } var dog1=new Dog(); dog1.sayName(); dog1.text .t =‘is write dog’; dog1.name=‘zhangsan’; console.log(dog1);
组合模式 在ES5中比较完美的一种创建对象的方式 function Dog(name,age){ this.name=name; this.age=age; this.arr=[];//这里是重复创建的,不会出现影响 } Dog.prototype.sayName=function(){ console.log(this.name); } var dog1=new Dog(‘xiaobai’,1); var dog2=new Dog(‘xiaohei’,2);
|