1、对于变量之间的传址和传值
(1)变量之间的传值只会将值赋给另一个办理而不会相互影响
//传值
var a=10;
var b=a;
b=5;
console.log(a);//10,这里的a的值不会改变
(2)但是复杂的数据类型会在赋值的同时进行传址,这样两个变量就会拥有同一个地址,改变其中一个就会影响另一个
传址:对象赋值取相同的内存地址
复杂数据类型一:对象
var obj1={
a:10,
}
var obj2=obj1;
obj2.a=5;
console.log(obj1.a);//5
复杂数据类型二:数组
//传址---会相互影响
var arr=[1,2,3,4,5];
var arr2=arr;
arr2[1]=6;
console.log(arr);//1,6,3,4,5
(3)传址会造成很多麻烦,所以我们可以进行深拷贝--只传值不传址 —json,这样就不会相互影响
根据不包含引用对象的普通数组深拷贝得到启发,不拷贝引用对象,拷贝一个字符串会新辟一个新的存储地址,这样就切断了引用对象的指针联系。
var arr3=JSON.parse(JSON.stringify(arr));
arr3[1]=0;
console.log(arr3);//1,0,3,4,5
console.log(arr);//1,6,3,4,5
(1)JSON.parse()函数
作用:将json字符串转换成json对象。
语法:JSON. parse(text[,reviver]).
参数:text 必须;一个有效的json字符串。
reviver 可选。
返回值:一个对象或数组。
(2)JSON.stringify()函数
作用:将json对象转换成json字符串。
语法:JSON.stringify(value [, replacer] [, space])
参数:value 必须;通常为对象或数组。
replacer 可选,用于转换结果的函数或者数组。
space 可选。向返回值 JSON 文本添加缩进、空格和换行符以使其更易于读取。
返回值:一个包含JSON文本的字符串。
这种深拷贝就是先将对象里面的数据转换为json字符串,再转化为对象,从而不会拷贝对象而传址
var objCopy={
name:"ghl",
age:22,
sex:"女"
}
console.log(objCopy);
=>console.log(JSON.stringify(objCopy));
==>{"name":"ghl","age":22,"sex":"女"}
console.log(JSON.parse(JSON.stringify(objCopy)));
==>2、工厂模式
工厂模式--可以避免变量污染 模拟类-已经被取代
function Factory(height){
//obj 人类
var objPeople={};
objPeople.name="ghl";
objPeople.age=22;
objPeople.height=height;
objPeople.hobby=function(){
console.log("我喜欢看电影");
}
return objPeople;
}
var newFactory=new Factory("180cm");
console.log(newFactory.height);
newFactory.hobby();
3、构造函数
取代工厂模式,把"属性"(property)和"方法"(method),封装成一个对象,从原型对象生成一个实例
//汽车对象的创建
function Car(name,color){
//obj.name=name;
this.name=name;
this.color=color;
this.action=function(){
console.log("跑");
}
}
var baoma=new Car("宝马","red");
console.log(baoma.name);
console.log(baoma.color);
baoma.action();
这里爱实例化对象的时候,“new”做了三件事
1、创建了空的对象
var obj={};
2、改变了this的指向:call aplly bind
Car.call(obj,"宝马","red");
3、赋值原型
obj.__proto__=Car.prototype;
构造函数是由构造自身和原型共同构成的,构造函数的原型 prototype,属性会写在构造函数里面,方法写在原型上,这样区分会使代码更加的清晰明了
function Person(name,age,height){
this.name=name;
this.age=age;
this.height=height;
}
//构造函数的原型 prototype可以给类添加方法
Person.prototype.action=function(){
console.log("姓名是"+this.name);//姓名是ghl,可以同this在方法中调用所有属性,这里的this指向是实例化的对象,即ghl
console.log("跑步");
}
Person.prototype.hobby=function(){
console.log("喜欢吃");
}
var ghl=new Person("ghl",22,"160cm");
ghl.action();//跑步
构造函数的属性也可以是私有的,这时候要访问或者设置就必须要通过方法去访问和设置
function Person(name){
//私有属性
var name=name;
//公有属性
this.height="179cm";
//get方法:通过共有方法去访问私有属性
this.get=function(){
return name;
}
//set方法:设置私有属性
this.set=function(newName){
name=newName;
console.log(name);
}
}
var xiaomi=new Person("xiaomi");
console.log(xiaomi.get());//xiaomi
xiaomi.set("ghl");// ghl
构造方法具有继承性,子类可以继承父类的属性和方法
function Dad(height){
this.name="zhangsan";
this.age=50;
this.height=height;
this.money="100万";
this.hobby=function(){
console.log("喜欢太极");
}
}
function Son(height){
//继承父类的属性和方法
Dad.call(this,height);
this.action=function(){
console.log("玩");
}
}
//实例化后可以调用父类的方法和属性
var newSon=new Son("180cm");
console.log(newSon.height);
console.log(newSon.money);//100万
newSon.hobby();//继承父类的方法
newSon.action();
子类是没有办法直接继承父级原型的方法,那么子类如何继承父类原型的方法但是却不会影响父级呢?可能我们首先想到的是
Student.prototype=Human.prototype;
这样去获得父级原型方法,这样确实可以继承原型,但是会涉及到传址问题,重写子级的方法会影响父级,那么如何解决传址问题呢?
这时候我们要重新写构造函数link,利用这构造函数去获得父级的原型上的方法,如何子级的原型对于link的实例化对象,这样就会获得link的所有方法,即为父级的原型上的方法new 实例化后会另起一个地址,从而不会影响父级但是可以实现对父级原型方法的继承
function Human(name,age){
this.name=name;
this.age=age;
this.body="眼睛,鼻子和嘴巴";
this.action=function(){
console.log("吃饭睡觉打豆豆");
}
}
Human.prototype.hobby=function(){
console.log("喜欢吃");
}
function Student(name,age){
Human.call(this,name,age);
}
//利用link来搭桥,获得原型方法但是不会传址而影响父级
function Link(){}
Link.prototype=Human.prototype;
//new 实例化后会另起一个地址,从而不会影响父级但是可以实现对父级原型方法的继承
Student.prototype=new Link();
var newStudent=new Student("ghl",22);
newStudent.action();
console.log(newStudent.body);
newStudent.hobby();//继承不了原型 报错
var human=new Human();
human.hobby();