构造函数与面向对象
<p>文章转自:<a href="https://segmentfault.com/a/1190000000602050">https://segmentfault.com/a/1190000000602050</a></p>
<h2>常用的几种对象创建模式</h2>
<h4>1. 使用字面量模式创建</h4>
<pre><code class="language-javasript">var people = {
name:'judy',
age:'18',
say:function(){
console.log('I am'+this.judy+this.age+'岁')
}</code></pre>
<h4>2.使用工厂模式</h4>
<pre><code class="language-javasript">function createPeople(name,age)
{
var o = new Object();
o.neme = name,
o.age = age,
o.say = function(){
console.log('I am'+name+age+'岁')
}
return o;
}
var Wayne = createPeople('Wayne','12');
var chenWei = createPeople('chenWei','88');
console.log(Wayne);//{neme: "Wayne", age: "12", say: ƒ}
console.log(chenWei);//{neme: "chenWei", age: "88", say: ƒ}
//=>工厂函数不能区分对象的基本类型</code></pre>
<h4>3.构造函数模式</h4>
<pre><code class="language-javasript">function People(name,age)
{
this.name = name;
this.age = age;
this.say = function(){
console.log('I am'+this.name+this.age+'岁')
}
}
var Wayne = new People('Wayne','12');
var chenWei = new People('chenWei','88');
//调用同一种方法却声明了不同的实例
console.log(Wayne.say == chenWei.say )//调用同一种方法false
//->面的方式似乎没什么不妥,但是我们可以发现,
//两个实例中调用的构造函数中的sayWhat方法**不是同一个Function实例**:
更改:
function People(name,age)
{
this.name = name;
this.age = age;
this.say = say;
}
//上面的方式似乎没什么不妥,但是我们可以发现,
//两个实例中调用的构造函数中的sayWhat方法不是同一个Function实例:
function say(){
console.log('I am'+this.name+this.age+'岁')
}
//没办法直接调用</code></pre>
<h3>4.原型对象模式</h3>
<ul>
<li>理解原型对象
<blockquote>
<p>当我们穿件一个函数时,该函数具备一个prototype属性,这个属性指向通过构造函数创建的那个函数的原型对象。通俗点就是原型对象就是内存中为其他对象提供共享属性和方法的对象。</p>
</blockquote></li>
</ul>
<p><img src="https://www.showdoc.cc/server/api/common/visitfile/sign/6fecdc26ebc84668485d395ca45da413?showdoc=.jpg" alt="" /></p>
<p>在原型模式中,不必再构造函数中定义实例属性,可以将属性信息直接赋予原型对象:</p>
<pre><code>function People(){
People.prototype.name = 'judy';
People.prototype.age = '12';
People.prototype.say =function(){
console.log('I am'+this.name+this.age+'岁')
}
}
var Wayne = new People();
Wayne.say();
var chenWei = new People();
chenWei.say();
console.log(Wayne);
console.log(chenWei);
//和构造函数不同的是这里新对象的属性和方法是所有实例都可以共享的,换句话说gf1和gf2访问的是同一份属性和方法。原型对象中除了我们赋予的属性外,还有一些内置的属性,所有原型对象都具备一个constructor属性,这个属性是一个指向包含prototype属性函数的一个指针(敢不敢再绕点!)。通过一幅图我们来清楚的理一下这个绕口的流程:</code></pre>
<p><img src="https://www.showdoc.cc/server/api/common/visitfile/sign/5fbb47604c27bec2ab7c543e2ea67b0b?showdoc=.jpg" alt="" />
<strong>所有的对象都有一个原型对象(prototype),原型对象中有一个constructor属性指向包含prototype属性的函数,Gf的实例gf1和gf2都包含一个内部属性指向原型对象(在firefox浏览器中表现为私有属性proto),当我们访问一个对象中的属性时,首先会询问实例对象中有没有该属性,如果没有则继续查找原型对象。</strong></p>
<pre><code class="language-javascript">- 使用原型对象创建
//可以通过字面量的形式创建一个对象
function People(){};
People.prototype={
name:'judy',
age:'12',
say:function(){
console.log('I am'+this.name+this.age+'岁')
}
}
//这里有一个地方需要特别注意下,constructor属性不再指向对象Gf,因为每定义一个函数,
//就会同时为其创建一个prototype对象,这个对象也会自动获取一个新的constructor属性,
//这个地方我们使用Gf.prototype本质上覆写了原有的prototype对象,
//因此constructor也变成了新对象的constructor属性,不再指向Gf,而是Object:
var Wayne = new People();
console.log(Wayne.constructor == Wayne) //false
console.log(Wayne.constructor == Object) //true
//也可以显性的定义constructor
People.prototype={
constructor:People,
name:'judy',
age:'12',
say:function(){
console.log('I am'+this.name+this.age+'岁')
}
}
console.log(Wayne.constructor == Wayne) //true </code></pre>
<h2>构造函数和原型的组合模式(在开发中经常用到)</h2>
<pre><code class="language-javascript">* 构造函数和原型组合模式
- 在实际开发中,我们可以用构造函数定义对象的属性,使用原型定义共享的属性和方法,
- 这样我们传递不同的参数来创建不同的对象,同时又拥有了共享的 方法和属性。
function People(name,age)
{
this.name = name;
this.age = age;
}
People.prototype={
constructor:People,
say:function(){
console.log('I am'+this.name+this.age+'岁')
}
}
var judy = new People('judy','12');
var Wayne = new People('Wayne','88');
//->1.在这个例子中,我们用构造函数定义了对象各自的属性值
//->2.在原型对象上,定义了constructor 和say()方法
//->好处:judy 和Wayne属性之间不会产生影响
</code></pre>
<p><a href="https://segmentfault.com/a/1190000000602050" title="构造函数与原型对象">构造函数与原型对象详解</a></p>
<h3>寄生式继承 <a href="https://blog.csdn.net/code_ja/article/details/51810779">https://blog.csdn.net/code_ja/article/details/51810779</a></h3>
<pre><code>function object(o) {
function F() {}
F.prototype = o;
return new F(); //创建实例
}
function inheritPrototype(c, p) {
var prototype = object(p.prototype);
prototype.constructor = c; //new p().constructor = c
c.prototype = prototype; //c.prototype = new p()
}
function Super(name) {
this.name = name;
this.colors = ['red', 'blue', 'green'];
}
Super.prototype.sayName = function() {
alert(this.name);
}
function Sub(name, age) {
Super.call(this, name);
this.age = age;
}
inheritPrototype(Sub, Super); //传入参数:(儿子,父亲)
console.log(new Sub('a','b').sayName()) //a
console.log(new Sub('c','cd').sayName()) //c
console.log(new Sub('c','cd'))
//以下是注释
[object Object] {
age: "cd",
colors: ["red", "blue", "green"],
constructor: function Sub(name, age) {
Super.call(this, name);
this.age = age;
},
name: "c",
sayName: function () {
alert(this.name);
}
}</code></pre>
<p><img src="https://www.showdoc.cc/server/api/common/visitfile/sign/026231a4a7b7146ac42c39b4a4b5cbb6?showdoc=.jpg" alt="" /></p>