咱们继续面向对象吧,此次是面向对象编程的第二篇,主要是讲建立对象的模式,但愿你们能从博客中学到东西。
时间过得很快,仍是不断的学习吧,为了本身的目标。html
//1.new Object() 建立对象 var person1 = new Object(); person1.name = "ry"; person1.age = 21; //2.对象字面量 var person2 = { name : "ry", age : 1 };
不足:前面这两种方法是能建立对象,可是有个不足就是,要建立不少对象时会有不少重复的代码,好比我再创个person3,又要打一次上面大部分的代码。
因此:做为一个有志青年,咱们有下面的解决方法,使用工厂模式。编程
工厂模式:声明一个函数,它封装了以特定接口建立对象的细节,并返回一个具体对象。数组
//工厂模式,声明一个工厂函数 funtion createPerson(name,age){ //建立一个对象 var obj = new Object(); //对对象属性赋值 obj.name = name; obj.age = age; obj.sayHi = { console.log("Hi"); }; //返回对象 return obj; }; //咱们一会儿就建立了3个对象 var p1 = createPerson("ry", 30); var p2 = createPerson("渊源远愿",31); var p3 = createPerson("阿元",21); console.log(p1.name); //"ry" console.log(p2.age); // 30 p2.sayHi(); //"Hi" p3.sayHi(); //"Hi"
因此:做为一个有志青年,咱们有下面的解决对象识别的方法,即便用构造函数模式。浏览器
构造函数咱们之前有据说过,好比建立数组时的Array(),建立时间的Date(),接下来咱们也能够自定义本身的构造函数了。函数
//Dog 构造函数,构造函数用个大写字母开头,以便和普通函数区分一下 function Dog (name , age ){ this.name = name; this.age = age; this.sayHi = function(){ console.log("Hi"); }; } //使用构造函数建立对象,3只狗狗 var dog1 = new Dog('lucy' , 1); var dog2 = new Dog('Jack' , 2); var dog3 = new Dog('Mc' , 3);
1.所谓"构造函数",其实就是一个普通函数,可是内部使用了this变量。
2.对构造函数使用new运算符,就能生成实例(就是这么先进),而且this变量会绑定在实例对象上。学习
▶比工厂模式好在这里:由于使用构造函数建立对象时对象实例会有一个constructor属性(构造函数属性),指向他的构造函数,那咱们就知道这个对象是人,仍是猫,仍是小猪了。测试
那就用代码说明一下:this
//上面的建立的3只狗狗:dog1,dog2 ,dog3,看看他们的constructor属性 console.log(dog1.constructor == Dog) //true console.log(dog2.constructor == Dog) //true console.log(dog3.constructor == Dog) //true //用instanceof 测试一下 //instanceof做用是测试某对象是否是某个类型。不记得就看看前面的博客哦 console.log(dog1 instanceof Dog); //true console.log(dog2 instanceof Dog); //true console.log(dog3 instanceof Dog); //true console.log(dog3 instanceof Object); //true 固然也是一个object类型
可是,构造函数仍是有不足的地方,好比上面你们都有一个sayHi函数(每一个对象共有的),咱们知道函数就是一个对象,在咱们每一次建立一个对象时都须要从新的建立sayHi函数,这会浪费内存空间,因此咱们要考虑把这个函数设置成共享的(只建立一次你们一块儿用)。
因此,做为一个有志青年,咱们看看原型模式prototype
1.首先咱们要先了解概念:不管何时,咱们建立的每个函数都有一个prototype属性,它指向原型对象(自动生成的一个对象)。
2.原型对象的做用是包含由特定类型的全部实例共享的属性和方法。(就是能保存让对象共享的属性和方法)。
你能够这样看的:若是你把原型对象理解成一个某类型的公共区域,也能够的。code
//原型模式 function Pig(){ //往Pig的原型对象添加属性和方法 Pig.prototype.name = "lucy"; Pig.prototype.age = 2; Pig.prototype.sayHi = function(){console.log('hi')}; } //建立对象 new pig1 = new Pig(); new pig2 = new Pig(); //你们都是共同的属性和方法,共享了 console.log(pig1.name); //"lucy" console.log(pig2.name); //"lucy" pig1.sayHi(); //"hi" pig2.sayHi(); //"hi" console.log(pig1.sayHi == pig2.sayHi()); //true
上面的例子,咱们将Pig的属性和方法都添加到了Pig.prototype(这就是原型对象了)中,因此由Pig建立的实例能共享这些属性方法。
咱们看图来了解构造函数,原型对象,对象实例之间的关系:
1.构造函数有prototype属性指向原型对象
2.原型对象有个constructor属性指回构造函数
3.每一个对象实例有个_proto_属性(浏览器支持的)指向原型对象
原型对象的出现,为了存放,对象实例的共享的属性和方法。
//测试一下pig1的原型对象是否是Pig.prototype console.log(Pig.prototype.isPrototypeOf(pig1)) // true
console.log(Object.getPrototypeOf(pig1) == Pig.prototype); //true
//为pig1重写name属性,该属性就会在实例自己。 pig1.name= "bigPig"; //hasOwnPrototype 做用是问name属性在对象实例本身身上吗,是就返回true console.log(pig1.hasOwnPrototype(name)); //true //对于pig2,咱们没有在对象实例中重写name,因此它的name属性源于原型对象,而不在pig2自己里面 console.log(pig2.hasOwnPrototype(name)); //false
//很明显这个方法和上面的hasOwnProperty是相对的 //在对象自己重写name,因此name在对象自己 pig.name = "bigPig"; //询问pig1中的name属性是否是在原型对象中 console.log(hasPrototypePorperty(pig1,"name")); //false //询问pig2中的name属性是否是在原型对象中,pig2没有重写name,因此在原型对象中 console.log(hasPrototypePorperty(pig2,"name")); //true
//pig1 有name属性 console.log("name" in pig1); //true //pig1 中没有weight 属性 console.log("weight" in pig1); //false
function Car (){ Car.prototype.name = "ryuan", Car.prototype.color = "red" } var car1 = new Car(); for(var prop in car1){ console.log(prop); } //输出: name color
function Car (){ Car.prototype.name = "ryuan", Car.prototype.color = "red" } console.log(Car.prototype); //["name", "color"]
由于原型对象也是个对象,因此咱们能够这样简便的定义原型对象。固然也是为了偷懒少打些代码,哈哈哈。优雅点,简单点,敲代码的方式简单点。
function Person(){}; //Person构造函数的原型对象,简单写法 Person.prototype = { name : "ry", age : 21, sayHi : function(){ console.log("hi"); } };
不足:这种写法也有很差的地方,就是这样写至关于重写了Person的原型对象。原型对象的constructor属性就再也不指向Person了。
//好比 var p1 = new Person(); console.log(p1.constructor == Person); //false //可是instanceof仍是可以判断对象是否是某类型 console.log(p1 instanceof Person); //true
若是constructor很重要的请况下:能够这样加上去
Person.prototype = { //加上这行,也就是定义constructor constructor: Person, name : "ry", age : 21, sayHi : function(){ console.log("hi"); } }
问题:原型模式只是一个共享区对吧,那我又要不共享的属性,那怎么办?
因此:做为一个有志青年,结合一下构造函数模式和原型模式吧。
这两种模式的结合能够说是最多用的,这是用来定义引用类型的默认方式。双剑合璧。
1.构造模式用于定义实例属性。
2.原型模式用来定义方法和共享的属性。
function Person(name , age , sex){ //这里定义实例的属性 this.name = name ; this.age = age ; this.sex = sex; } //下面定义共享的属性和方法 Person.prototype = { constructor : Person , sayHi : function (){ console.log("hi"); } } //建立你的对象吧 var girl = new Person("玲玲",18,"female"); var boy = new Person ("元元",20,"male"); //各自的名字 console.log(girl.name); //"玲玲" console.log(boy.name); //"元元" //打招呼 girl.sayHi(); //hi boy.sayHi(); //hi
本次主要是怎么去建立对象和怎么去定义本身的引用类型。慢慢理解理解,慢慢吃透,欢迎你们一块儿讨论。
找不到对象,咱们仍是本身建立吧,哈哈哈。作个积极向上的人,对象总会有的。
不忘初心,方得始终。以为博主写得很好就赞一下吧,也能够关注俺哦。
同系列前几篇:
第一篇:JavaScript--我发现,原来你是这样的JS(一)(初识)
第二篇:JavaScript--我发现,原来你是这样的JS(二)(基础概念--躯壳篇)
第三篇:JavaScript--我发现,原来你是这样的JS(三)(基础概念--灵魂篇)
第四篇:JavaScript--我发现,原来你是这样的JS(四)(看看变量,做用域,垃圾回收是啥)
第五篇:JavaScript--我发现,原来你是这样的JS(引用类型不简单[上篇],且听我娓娓道来)
第六篇:JavaScript--我发现,原来你是这样的JS(引用类型不简单[下篇],基本包装类型与个体内置对象)
第七篇:JavaScript--我发现,原来你是这样的JS:面向对象编程OOP[1]--(理解对象和对象属性类型)
本文出自博客园:http://www.cnblogs.com/Ry-yuan/ 做者:Ry(渊源远愿) 欢迎转载,转载请标明出处,保留该字段。