构造函数的形式
1,使用new关键字创建对象
2,使用构造函数,把新创建出来的对象,赋值给构造函数内的this
3,在构造函数内使用this为新创建出来的对象新增成员
4,默认返回新创建的这个对象
function Animal(name,type,){ this.name =name; this.type =type; this.barkWay = function(){ console.log('汪汪汪') } } var dog =new Animal('大黄','dog'); dog.barkWay();//汪汪汪
注意:如果想使用正常的函数一样使用构造函数
1,构造函数中的this将不再指向新创建出来的对象
2,构造函数中的this这个时候多指向window对象,当使用this给对象添加成员的时候,全部添加到window上
构造函数存在的问题
构造函数中的方法,每新创建一个对象的时候,该对象都会重新创建方法,每个对象独占一个方法,但是该方法内容完全相同,所以造成资源浪费
function Animal(){ this.name = '大黄'; this.type ='dog'; this.age =15; this.bark = function(){ console.log('汪汪汪') }}var dog = new Animal();var cat = new Animal(); dog.bark();//汪汪汪 cat.bark();//汪汪汪
解决方法1
将构造函数内的房进行提取放到构造函数外面,在构造函数内部引用,那么创建出来的对象,都会指向构造函数外面的这个函数,达到共享的目的
function barkWay(){ console.log(this.type +this.yell) } function Animal(name,type,yell){ this.name = name; this.type = type; this.yell =yell; this.bark =barkWay; } var dog = new Animal('大黄','狗','汪汪汪'); var cat = new Animal('小花','猫','喵喵喵'); cat.bark();//猫喵喵喵 dog.bark();//狗汪汪汪
问题:全局变量增多,造成全局变量污染,代码结构混乱,不易维护
解决方法2
使用原型
function Animal(name,type,yell){ this.name = name; this.type = type; this.yell =yell; } Animal.prototype.bark =function(){ console.log(this.type + this.yell) }; var dog = new Animal('大黄','狗','汪汪汪'); var cat = new Animal('小花','猫','喵喵喵'); cat.bark();//猫喵喵喵 dog.bark();//狗汪汪汪
原型: 在构造函数创建出来的时候,系统会默认的创建并关联一个对象,这个对象就是原型,原型对象默认是空对象
原型的作用:原型中的成员,可以被使用和它关联的构造函数创建出来的所有对象共享
当使用对象访问属性和方法的时候,会首先在对象内部进行查找,如果找到了,就直接使用,如果没有找到,就去原型中查找,查找到之后使用,如果原型中没有,如果是属性就是undefined,如果是方法就是报错
function Person(name,age,sing){ this.name = name ; this.age =age; this.sing =sing; } Person.prototype.sayHello = function(){ console.log("你好我是"+this.name);}; Person.prototype.singName = function(){ console.log(this.sing) }; var p = new Person('张学友',18,'一千个伤心的理由'); var p1 = new Person('刘德华',28,'忘情水'); p.sayHello();//你好我是张学友 p1.sayHello();//你好我是刘德华 p.singName();//一千个伤心的理由 p1.singName();//忘情水
原型对象的使用
1,使用对象的动态特性,为原型对象添加成员
2, 直接替换原型对象
如果使用第二种方法使用原型,会出现如下问题
在替换原型之前创建的对象和在替换原型之后的创建的对象的原型,,不是同一个
function Person(name,age,sing){ this.name = name ; this.age =age; this.sing =sing; } Person.prototype.sayHello = function(){ console.log("你好我是"+this.name);//你好我是刘能}; var p = new Person('刘能',18,'male'); p.sayHello(); Person.prototype ={ msg:'你猜我在不在' }; var p1 =new Person('刘二狗',24,'male'); console.log(p1.msg);//你猜我在不在 p1.sayHello();//Uncaught TypeError: p1.sayHello is not a function p.sayHello();//Uncaught TypeError: p.sayHello is not a function
使用原型的注意事项
1,使用对象访问属性的时候,如果在本身内找不到就 回去原型中查找,但是使用点语法进行属性赋值的时候,并不会去原型中进行查找,使用点语法赋值的时候,
如果对象不存在该属性,就会给该对象新增该属性,而不会修改原型中的属性
function Person(){ } Person.prototype.name ="张三"; Person.prototype.age =18; var p = new Person(); console.log(p.name);//张三 p.name ="李四"; console.log(p.name);//李四 var p1 =new Person(); console.log(p1.name)//张三
2,如果在原型中的属性是引用类型的属性,那么所有对象共享该属性,并且一个对象修改了该引用类型中的成员,其他都会受到影响
function Person(){ } Person.prototype.name ="张三"; Person.prototype.age =18; var x = { brand:'奥迪', type:'A7' }; Person.prototype.car =x; var p = new Person(); console.log(p.car.brand);//奥迪 Person.prototype.car ={ brand: 'BYD' }; var p1 =new Person(); console.log(p.car.brand);//BYD console.log(p1.car.brand);//BYD
3,一般情况下不会讲属性添加到原型中,只会将需要共享的方法,添加到原型对象中