发表于: 2017-02-28 22:56:48

1 1345


一、今天完成的事情:

1.完成了萝卜多最后的demo;

2.听梦妮说了萝卜多三期需求讲解;

3.重新学习了面向对象,理解更深入了;


二、明天要做的事情:

1.深入理解需求,做完项目评审需要的东西;


三、今天遇到的问题:

1.构建对象的几种模式:第一种是工厂模式,顾名思义,就跟工厂一样,它返回它内部所有的值,我的理解:它内部返回一个对象,我们传入的参数,就是内部对象的属性值,在这种模式中,我们虽然可以创建多个相似的对象,但是并不能识别我们生成的对象的类型
function man(name,age,sex) {
    return {
        name:name,
        age:age,
        sex:sex
    }
}
第二种:构造函数模式
 function Man(name,age,sex) {
     this.name name;
     this.age age;
     this.sex sex;
     this.sayNmae function () {
         alert(this.name);
     }
  }
  var person1 = new Man('frank',25,'man');
var person2 =  new Man('lina',2,'woman');
console.log(person1,person2)
person2.sayNmae()
我们可以对比一下工厂模式和构造函数模式的不同
1.构造函数模式没有显示的创建对象;
2.构造函数模式最后没有return;
3.构造函数模式直接将属性和方法赋给了this。
当然,根据约定,我们的构造函数的首字母都需要大写,来跟其他函数进行区分。
当我们new的时候,发生了什么:
1.创建一个新对象;
2.将构造函数中的作用域赋给新对象(this就指向这个新对象咯);
3.运行构造函数内部的方法,给新对象添加属性;
4.返回新对象。
每个新的对象都会有一个constructor属性,只想原构造函数,创建自定义构造函数可以将它的实例标识为特定类型。
构造函数详解:
1.构造函数和其他函数唯一的区别就是调用它们的方法不同,普通函数我们依靠名称调用,而构造函数我们通过new来调用
2.构造函数的缺点是:如果this中有方法,那他也会new一个这个方法,也即重新创建这个方法的实例;所以我们person1和person2虽然都是sayname的实例,但是它们俩并不是一个东西。
所以如何解决这个问题呢,我们引入了原型模式;
原型模式:首先上一段代码,大家体会一下有什么不同:

 function Man(name,age,sex) {
     this.name name;
     this.age age;
     this.sex sex;
     Man.prototype.sayNmae function () {
         alert(this.name);
     }
  }
  var person1 = new Man('frank',25,'man');
var person2 =  new Man('lina',2,'woman');

console.log(person1,person2)
person2.sayNmae()
1.什么是原型:当生成一个函数的时候,函数下面会自带一个prototype属性,指向它的原型(扩展知识:在它的原型中有constructor指向函数本身),这个原型你可以把它理解为一个对象,它包含了这个函数所有需要共用的信息。意思是我们不会再函数实例中创建我们需要的信息,可以直接在它的原型对象中创建,当我们使用new的时候,也能在新的函数中访问到它的原型信息。
2.如何在new中取到原型对象中的信息:在我们new出来的变量中,有一个_proto_属性,它在外部是访问不到的,它指向了构造函数的原型对象,我们在进行属性搜索的时候,会首先搜索实例中有没有这个属性,如果没有它会继续搜索原型对象,如果原型对象中有这个属性,它就会返回这个属性的值。所以,我们函数在查找我们需要的属性的时候,如果实例中没有,它就会查找两次,一次是在实例中,一次是在原型对象中。
3.如何检测当前获取到的属性来自实例还是原型对象:obj.hasOwnProperty('attr')如果attr来自实例,它会返回true否则会是false,当然,如果在函数的实例和原型中都没有它也会返回false,这种情况下应该怎么办呢?这里我们引入in操作符,'attr' in obj 当obj中有该属性时,它会返回true,不管它是在原型还是实例中,用以下方法就能看出属性是在原型还是实例中:
function test(obj,name) {
    return !obj.hasOwnProperty(name)&& name in obj   //当它在原型中它才会返回true
}
4.如果我们在构造函数的实例之中修改原型,是修改不到的。
5.如果先声明了构造函数的实例,然后修改了它的原型对象,这样会导致它的原型对象和以前的完全隔离。在高程中,有说到这样一句话,“重写原型对象切断了现有原型与任何之前已经存在的实例对象之间的联系。它们引用的仍然是最初的原型”。这句话可以理解为,当我重写了原型对象之后,我以前new出来的构造函数的实例中的_proto_都还是会之前以前没有更改之前的原型:
function Person() {
}
var friend = new Person();
Person.prototype {
    constructor : Person,
    name 'frank',
    sayName function () {
        alert(this.name)
    }
}

console.log(friend.name)
friend.sayName();
这样写的后果是:第一个是undefined,第二个会报错,如果把new操作移入到更改原型之下,就能够正常显示。
6.我们所有的原生引用类型(obj、arr、string)你都可以把它想象成一个构造函数,在这个构造函数的prototype中,有各种我们平时需要用到的方法,比如数组的slice,string的substring,等等,这就意味着,我们可以给它们添加方法。但是并不推荐更改原生对象的原型,因为你可能更改到原生对象的原型,导致未知的错误。
7.但是如果单独使用原型模式也会有弊端,因为在原型中的各种东西都是共享的,上一段代码
function Man(name,age,sex) {
     this.name name;
     this.age age;
     this.sex sex;
     Man.prototype.friend ['lina','bob']
  };
var person1 = new Man('frank',25,'man');
var person2 =  new Man('lina',2,'woman');
person1.friend.push('selina')
console.log(person1.friend);
console.log(person2.friend);
在这一段代码中,我们的初衷只是在person1中的friend添加一个,但是事实是我们person1也从原型中继承了它添加的friend,所以我们很少单独使用原型模式。
8.构造函数模式和原型模式共同使用:我们现在更改一下上面的例子:
 function Man(name,age,sex) {
     this.name name;
     this.age age;
     this.sex sex;
     this.friend ['lina','bob'];
     Man.prototype.sayFriends function () {
         console.log(this.friend);
     }
  };
var person1 = new Man('frank',25,'man');
var person2 =  new Man('lina',2,'woman');
person1.friend.push('selina')
person1.sayFriends();       //["lina", "bob", "selina"]
person2.sayFriends();       //["lina", "bob"]
我们将friend作为构造函数的一条写进了函数中,将他们共有的方法写入了原型中,所以在我们调用原型中的sayFriends方法,就能正确的看到他们应该有的朋友。
8.动态原型模式:运用这个模式来判断是否需要初始化原型,一条if就能够实现,如果我们需要判断多条属性或者方法,我们只需要判断一条就够了,如果一条没有,其他全给他加上,不过要注意,这种方法不能重写原型,因为重写原型会导致最初的原型和现在的原型完全不同。上一段代码:
function Man(name,age,sex) {
    this.name name;
    this.age age;
    this.sex sex;
    this.friend ['lina','bob'];
    if (typeof this.sayFriends != 'function'){
        Man.prototype.sayFriends function () {
            console.log(this.friend);
        }
    }
 };
注意后面检测部分,如果没有这个东西,我就会创建它,但是这个我没有想到具体用于哪里。。很尴尬



返回列表 返回列表
评论

    分享到