彻底理解工厂函数、构造函数、原型,原型对象,原型链
<!-- 创建一个对象 --> <script> var obj = { name:"孙悟空", age:18, gender:"男", sayName:function(){ alert(this.name) } } obj.sayName(); </script>
先看一下上面的代码,在了解原型及原型链之前,让我们先看一下使用工厂方法创建对象的知识:
如上代码所示,创建一个对象不过瘾,我现在创建三个对象:
<script> var obj = { name:"孙悟空", age:18, gender:"男", sayName:function(){ alert(this.name) } } var obj2 = { name:"猪八戒", age:28, gender:"男", sayName:function(){ alert(this.name) } } var obj3 = { name:"沙和尚", age:38, gender:"男", sayName:function(){ alert(this.name) } } </script>
上面第2/3个对象是直接复制粘贴的,那如果我想创建10个对象,那是不是要复制粘贴10次呢?
很显然,不现实。那能不能用一个比较简单的办法去处理这个问题呢?答案肯定是可以的。在这里我们可以使用工厂方法创建对象,通过该方法可大批量的创建对象。
<!-- 创建一个对象 --> <script> function createPerson() { //创建一个新的对象 var obj = new Object(); //向对象中添加属性 obj.name = "孙悟空"; obj.age = 18; obj.gender = "男"; obj.sayName = function () { alert(this.name); }; //将新的对象返回 return obj; } var obj2 = createPerson() var obj3 = createPerson() var obj4 = createPerson() console.log(obj2) console.log(obj3) console.log(obj4) </script>
打印出来的结果:
但如果我想让name打印出猪八戒就不能实现了,因为里面的数据已经写死了,除非你将构造函数里的object.name = 孙悟空 换成 object.name = 猪八戒 但那样是不是很不方便?
答:是的。
所以我们可以用传参的形式去写,具体写法如下:
你把属性给传过去,它给你返回一个对象,这就是工厂函数的作用。构造函数中那些重复性的代码,我们不用再写了。
以上就是使用工厂方法创建对象的步骤。
---------------------------------------------------------------------------------------------------
下面来了解下构造函数
<script> function createPerson(name, age, gender) { //创建一个新的对象 var obj = new Object(); //向对象中添加属性 obj.name = name; obj.age = age; obj.gender = gender; obj.sayName = function () { alert(this.name); }; //将新的对象返回 return obj; } // 用来创建狗的对象 function createGog(name, age) { var obj = new Object(); obj.name = name; obj.age = age; obj.sayHello = function(){ alert("旺旺~~") } return obj; } var obj2 = createPerson("猪八戒",18,"男") var obj3 = createPerson("白骨精",28,"女") var obj4 = createPerson("蜘蛛精",38,"男") //创建一个狗的对象 var dog = createGog("旺财",3) console.log(dog) console.log(obj4) </script>
我们可以看到,打印出了两个对象,一个人的对象,一个狗的对象,但是这样的话就没法区分类型。
<script> function Person(name, age, gender) { this.name = name; this.age = age; this.gender = gender; this.sayName = function () { alert(this.name); }; } var per = new Person("孙悟空", 18, "男"); var per2 = new Person("玉兔精", 16, "女"); var per3 = new Person("奔波霸", 38, "男"); console.log(per); function Dog() { } var dog = new Dog(); console.log(dog); </script>
记住:
1.使用同一个构造函数创建的对象,我们称为一类对象,也将一个构造函数称为一个类。比如说per per2 per3就属于同一个Person类
2.我们将通过一个构造函数创建的对象,称为是该类的实例 比如说 per是Person1的实例 per2是Person的实例 per3也是Person3的实例,dog是Dog类的实例
<script> function Person(name, age, gender) { this.name = name; this.age = age; this.gender = gender; this.sayName = function () { alert(this.name); }; } var per = new Person("孙悟空", 18, "男"); var per2 = new Person("玉兔精", 16, "女"); var per3 = new Person("奔波霸", 38, "男"); console.log(per); function Dog() { } var dog = new Dog(); console.log(dog); console.log(per instanceof Person); console.log(dog instanceof Person);
</script>
打印的结果:
console.log(dog instanceof Person);//true
console.log(dog instanceof Dog);//true
this补充
---------------------------------------------------------------------------------------------------
好了,再让我们看看原型和原型对象的概念。
<script> function Person(){ } console.log(Person.prototype) </script>
打印出来的结果:
不仅是Person,如果我来一个MyClass函数也是如此
<script> function MyClass() { } console.log(MyClass.prototype) </script>
下面做一个测试,看看每个函数的prototype相不相等?
<script> function Person() { } function MyClass() { } console.log(Person.prototype == MyClass.prototype) </script>
结果为
因此说明了,每个函数都有自己的prototype.那prototype是干嘛的呢?
<script> function MyClass() { } var mc = new MyClass() console.log(mc.__proto__) </script>
注意:mc.__proto__和MyClass.prototype指向的是同一个对象,通过下面代码可验证:
<script> function MyClass() { } var mc = new MyClass() console.log(mc.__proto__ == MyClass.prototype) </script>
<script> function MyClass() { } var mc = new MyClass() var mc2 = new MyClass() console.log(mc2.__proto__ == MyClass.prototype) </script>
因此,通过构造函数创建的对象指向的是同一个原型对象
<script> function MyClass() { } //向MyClass的原型中添加属性a MyClass.prototype.a = 123 var mc = new MyClass() var mc2 = new MyClass() console.log(mc.a)//123 </script>
如果我们主动向mc中添加属性呢?
<script> function MyClass() { } //向MyClass的原型中添加属性a MyClass.prototype.a = 123 var mc = new MyClass() var mc2 = new MyClass() mc.a="我是mc中的a" console.log(mc.a) //我是mc中的a
</script>
<script> function MyClass() { } //向MyClass的原型中添加属性a MyClass.prototype.a = 123 //向MyClass的原型中添加一个方法 MyClass.prototype.sayHello = function(){ alert("hello") } var mc = new MyClass() console.log(mc.a) mc.sayHello() </script> //弹窗hello
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
原型链的深入理解
<script> function MyClass() { } //向MyClass的原型中添加一个name属性 MyClass.prototype.name = "我是原型中的名字" var mc = new MyClass()
console.log("name" in mc) </script> //true
console.log(mc.hasOwnProperty("name"));//false