javascript 学习笔记(1)对象和原型

来源:互联网 发布:淘宝类目数据 编辑:程序博客网 时间:2024/06/04 18:18

想着以前学的js都是看着jqeury这种框架写写不痛不痒的函数,终究感觉还是不爽。找了个机会,说服自己,沉下心来看看js方面的书(目前是《javascript高级程序设计》),系统的学习一下。

这里就当时写给自己看的读书笔记,如果有朋友看了觉得肤浅轻喷,或者有不同的见解也请教教我,毕竟自己要学的东西还是太多了。


由于是读书笔记,因此一些基本的自己觉得不用写的就没放上来了,

so..第一个要讲的就是js的对象和原型链


对象:js中的Object说白了就是一组无序键值对的集合,这个就不用多说了。


创建对象哪家强?


1. 工厂方法:就是写个方法创建一个object然后给他赋属性最后返回对象,最原始就不多说了


2. 构造函数:

例子:

function Person(name,age){this.name = name;this.age = age;        this.sayHi = function(){        alert(this.name);        };}
值得注意: 1. 没有显式创建对象 2.直接复制给this 3. 没有return

使用方法:

var person = new Person("Roger",25)
执行顺序:

1.创建一个新的对象 2. 将构造函数作用域赋给该对象(this指向该对象) 3.执行构造函数中的代码(添加属性) 4. 返回该对象


上面的代码看上去很完美,实际上有个问题:sayHi后的是一个函数表达式,即可以改写为:

this.sayHi = new Function("alert(this.name)");
然后你就发现,每创建一个Person,你就new了一个方法对象,显然不科学。(这里我写博客的时候都忘记了,还是印象不深刻啊)


怎么解决呢,你当然可以定义一个全局函数,然后sayHi指向它,但问题是,你这么到处定义全局函数,有没有考虑过global的感受

因此,我们就引入了下个概念:原型

原型

每一个函数都有一个prototype(原型)属性这个对象是一个指针,指向一个对象。这个对象的用途是包含可以由特定类型的所有实例

共享的属性和方法,注意共享两个字,就解决了我们上面所看到的方法冗余的问题。

具体例子:

function Person(){};Person.prototype.name="Roger";Person.prototype.age=29;Person.prototype.sayHi=function(){   alert(this.name);};var p1 = new Person();p1.sayHi();//alert "Roger"


原型的原理:

创建一个Person的对象p1时,有一个内部属性[[prototype]],指向了Person.prototype。

然后,虽然我们的p1自己并没有定义sayHi函数,但是它却可以调用sayHi函数,这是为何?

这是通过对象属性查找的过程来实现的。

当我们调用sayHi的时候,首先会在p1实例本身开始找,找不出之后,就继续搜索p1的原型对象,这时我们发现

原型对象中存在sayHi这一属性,则返回,这就是我们能够调用了sayHi的原因了。

另外我们知道Person.prototype只有一个,所有Person实例的内部属性[[prototype]]都指向它,这也就成了原型对象的方法和属性能够

在实例间共享的原因了。


你以为你改了,实际上你只是覆盖了它。

说到共享,自然,我们之前定义的

Person.prototype.name="Roger";

也是共享的,那是不是我们修改了一个实例的name,另外一个实例也能反映出来呢?

var p1 = new Person();var p2 = new Person();p1.name = "Rachel";p1.sayHi();//alert "Rachel"p2.sayHi();//alert "Roger"

从上面这个例子,有朋友就会说,你看,没有共享。实际上就如最开始所说的,你以为你改了,实际上你是在p1这个对象上增加了一个

叫name的属性,然后赋值为Rachel,prototype对象上的没动,这样在p1.sayHi中,由之前的属性对象查找你就知道,首先在p1对象上

就已经找到了name,就直接返回了,根本没有到prototype,因此就造成了属性不共享的假象。


有了原型,我们就解决了方法的共享问题,但是很明显,原型也有自己的缺陷,而且它的缺陷正是它的优点:啥属性都共享啊,特别对于

引用类型,问题尤其突出,不信你看:

function Person(){};Person.prototype.name="Roger";Person.prototype.age=29;Person.prototype.friends=['Maigo','Scottie'];Person.prototype.sayHi=function(){   alert(this.name);};var p1 = new Person();p1.friends.push('PepsiLight');var p2 = new Person();alert(p1.friends);//alert "Maigo,Scottie,PepsiLight"alert(p2.friends);//alert "Maigo,Scottie,PepsiLight"

那该怎么办呢?大家肯定就懂了,把这两个方法组合一下嘛:属性的初始化放在构造函数里面,方法初始化放在原型里面。

正解。

今天就到这里,下一节讲原型链和继承


0 0
原创粉丝点击