包装对象、对象常用操作、继承
一、 包装对象
* 在js内部,当我们去调用字符串、数字、布尔值这些基本数据类型的属性或者方法的时候,js会在内部先把这些基本数据类型转成一个对应的对象类型(包装对象),然后再去调用包装对象身上的这些属性或者方法
*
* 包装对象有
* String
* Number
* Boolear
*
* 注意:
* 1、null与undefined没有对应的包装对象
* 2、基本数据类型只能使用对应的包装对象身上的属性或者方法,不能添加
* 因为使用后,包装对象就消失了,所以只能用,不能添加
var str='kaivon';
console.log(str.charAt(0)); //k
console.log(str.length); //6
console.log(str.substring(1)); //aivon
//内部执行的过程
/*var str=new String('kaivon');
console.log(str.length);*/
var num=12.456;
console.log(num.toFixed(2)); //12.46 把数字转成字符串,并用四舍五入的方法截取小数点后面的位数
//内部执行的过程
/*var num=new Number(12.456);
console.log(num.toFixed(2));*/
//基本数据类型只能用对应包装对象身上的方法或者属性,不能添加
var str1='kaivon1';
str1.a=12;
console.log(str1.a); //undefined
二、hasOwnProperty
* 作用
* 判断一个属性是不是自己对象身上的(主语是对象,不会找到原型更不会找到Object),(主语是原型,就只在原型身上找)
* 语法
* 对象.hasOwnProperty(属性)
* 参数
* 要检测的属性
* 返回值
* true 自身属性
* false 非自身属性
* 注意
* 1、这个方法是Object身上的方法
* 2、不会顺着原型链往外面去查找属性,只查找自身
function Person(name){
this.name=name;
}
Person.prototype.country='china';
var p1=new Person('kaivon');
console.log(p1.name); //kaivon
console.log(p1.country); //china
console.log(p1.hasOwnProperty('name')); //true
console.log(p1.hasOwnProperty('country')); //false 因为这个属性在原型身上
三、constructor
* 概念
* 每个对象身上都会有这个属性,默认指向该对象对应的构造函数
* 这个属性不是放在对象身上,放在对应的原型对象身上
* 作用
* 查看对象的构造函数(构造函数的函数名)
* 语法
* 对象.constructor
* 返回值
* 对象的构造函数
* 注意:
* 这个属性是可以被修改的
function Coder(name){
this.name=name;
}
/**Coder.prototype.age=18;
Coder.prototype.sex='男';*/ //这种写法没有问题
Coder.prototype={
constructor:Coder, //这种写成对象的写法,会不经意间把constructor改成别的,所以也就自己把constructor设定为对应的构造函数的名字
age:18,
sex:'男'
};
console.log(c1.constructor==Coder); //ture
四、for in
for(var attr in obj){
console.log(attr,obj[attr]);
}
//如果不想找到原型添加的属性---通过hasOwnProperty判断
//如果只想遍历自己身上的属性
for(var attr in arr){
if(arr.hasOwnProperty(attr)){
console.log(attr,arr[attr]);
}
}
五、instanceof
* 作用
* 二元运算符,和==,>,<是同一类东西,用来查找对象与构造函数在原型链上有没有关系
* 语法
* 对象 instanceof 构造函数
* 返回值
* true 有关系
* false 没关系
*
* 可以用来做类型判断
function Person(name){
this.name=name;
}
var p1=new Person('kaivon');
console.log(p1 instanceof Person); //true
console.log(p1 instanceof Array); //false
console.log(p1 instanceof Object); //true
六、toString
* 作用
* 把对象类型转成字符串
* 注意
* 系统对象下的这个方法都是它对应原型对象身上的方法,自己写的对象下的这个方法是属于Object原型身上的方法
//用toString做类型判断
var num=0;
var str='kaivon';
var b=true;
var n=null;
var u=undefined;
var arr1=[];
var obj1={};
var fn=function(){};
var d=new Date();
var re=new RegExp();
console.log(Object.prototype.toString.call(num)); //[object Number]
console.log(Object.prototype.toString.call(str)); //[object String]
console.log(Object.prototype.toString.call(b)); //[object Boolean]
console.log(Object.prototype.toString.call(n)); //[object Null]
console.log(Object.prototype.toString.call(u)); //[object Undefined]
console.log(Object.prototype.toString.call(arr1)); //[object Array]
console.log(Object.prototype.toString.call(obj1)); //[object Object]
console.log(Object.prototype.toString.call(fn)); //[object Function]
console.log(Object.prototype.toString.call(d)); //[object Date]
console.log(Object.prototype.toString.call(re)); //[object RegExp]
在对象原型下将对象类型转成字符串,call修正this的指向
七、call
* 作用
* 调用函数并且改变this的指向
* 语法
* 函数名.call(thisArg,arg1,arg2...)
* 参数
* thisArg 函数中this指向的值
* arg1,arg2... 从call里的第二个参数开始,都是真正函数里的参数
* 返回值
* undefined
*
* 注意:thisArg的值为null或者undefined的时候,this是指向window
function fn(){
console.log(this);
}
fn(); //window
fn.call(1); //this指向数字
fn.call('kaivon'); //this指向字符串
fn.call('true'); //this指向布尔值
fn.call([1,2,3]); //this指向数组
fn.call({}); //this指向对象
fn.call(null); //this指向window
fn.call(undefined); //this指向window
function fn1(name,age){
console.log(this,name,age);
}
fn1.call(1,'Sigo',18); //Number 'Sigo' 18
fn1('Sigo',18); //window 'Sigo' 18
apply的作用和call的作用一样只是语法不一样
八、赋值与赋引用
基本数据类型
var str1='kaivon';
var str2='kaivon';
console.log(str1==str2); //true
//基本数据类型的赋值,就是把值复制了一下
var n1=2;
var n2=n1+5;
console.log(n1,n2); //2 7
//基本数据类型的比较,比较的是值相等就相等
var n3=10;
var n4=10;
console.log(n3==n4); //true
复杂数据类型
var obj1={a:10,b:20};
var obj2={a:10,b:20};
console.log(obj1==obj2); //false 数值是相同,但是内存的引用地址不一样
//复杂数据类型的比较,比较的不光是值,并且还要比较引用地址,如果两个都相等,那他们就相等
var obj3={a:10,b:20};
var obj4=obj3;
console.log(obj3==obj4); //true
//复杂数据类型的赋值,它不光把值复制了一下,并且还复制了一下在内存中的引用地址
var arr1=[1,2,3];
var arr2=arr1;
arr2.push(4); //arr2与arr1的引用地址是相同的,所以无论修改哪个,两个都会变
console.log(arr2); //[1, 2, 3, 4]
console.log(arr1); //[1, 2, 3, 4]
var arr3=[4,5,6];
var arr4=arr3;
arr4=[7,8,9]; //arr4又赋值了,所以就又开了一块内存,引用地址就不一样了
console.log(arr4); //[7, 8, 9]
console.log(arr3); //[4, 5, 6]
九、浅拷贝与深拷贝
//拷贝就是将一个对象的值复制到另一个对象那里去,但是应用地址不一样, 所以两个对象之间就不会有关系了。
//这是浅拷贝,既考虑不那么周到,如果对象的值也有对象就不适用
window.onload=function(){
var p1={a:1,b:20};
function a(obj){
var newObject={};
for( attr in obj){
newObject[attr]=obj[attr];
}
return newObject;
}
var p2=a(p1);
p2.a=10;
console.log(p2); //a: 10 b:20
console.log(p1); //a:1 b:20
}
//深拷贝
var p3={
a:1,
b:[20,10,30],
c:{
d:40
}
}
function b(obj){
var newObject={};
if(typeof obj !='object'){
return obj;
}
//如果要复制的对象里有个属性的值是数组,那复制的结果就必需还是数组
if(obj instanceof Array){
//obj.constructor==Array这个判断条件也可以
newObject=[];
}else{
newObject={};
}
for( attr in obj){
newObject[attr]=b(obj[attr])
}
return newObject;
}
var p4=b(p3);
console.log(p4);
十、继承
* 属性继承
* 通过call的方法调用构造函数继承属性
* 方法继承
* 通过for in的方法继承原型身上的方法
*
* 注意:
* 1、继承其它对象的属性的时候,一定要用call去修正一下this的指向
* 2、继承其它对象的方法的时候,不能直接赋值,要用for in的方法去赋值,不然会出现对象引用的关系(引用地址 )继承属性
function Person(name,age){
this.name=name;
this.age=age;
}
//创建一个对象
function Coder(name,age,job){
/*this.name=name;
this.age=age;*/
//Person(name,age); 直接调用函数(普通函数调用方式)的话,this指向了window,就会有问题 ,
Person.call(this,name,age);
this.job=job;
}
方法继承
function Person(name){
this.name=name;
}
Person.prototype.say=function(){
console.log('我叫'+this.name);
}
var p1=new Person('Sigo');
//创建一个对象
function Coder(name,job){
Person.call(this,name); //属性继承
this.job=job;
}
for(var attr in Person.prototype){
//Coder.prototype[attr]=Person.prototype[attr];
//如果只想继承构造函数原型身上自己的方法,就需要做以下的判断
if(Person.prototype.hasOwnProperty(attr)){
Coder.prototype[attr]=Person.prototype[attr]; //将Person原型say的方法继承给Coder了
}
}
Coder.prototype.coding=function(){
console.log('我的工作是'+this.job+',我正在加班');
}
var c1=new Coder('Sigo','前端');
c1.say(); //我叫Sigo
p1.say(); //我叫Sigo
c1.coding(); //我的工作是前端,我正在加班