原型链方法使用实例讲解
有下列例子
function Foo() {
}
Foo.prototype.getName = function () {
alert(3);
};
var foo = new Foo();
foo.getName();// 3;
Foo.getName();// Foo.getName is not a function
问题:
1、var foo = new Foo();这一句语法到底做了那几件事?
2、为什么在Foos上定义的原型方法,使用Foo调用不出来?
回答:
1、“
var foo = new Foo();
”在这个语句中我们声明了一个foo对象,用“Foo()”这一个构造函数来初始化foo对象,赋予初始值。这个过程被称之为对象的实例化。
也就是由抽象到具体的过程。
Foo在这个例子中被创建为一个构造函数,这个语句与“ var foo = new Array ();”类似,Array也是构造函数。可以理解为,
创建了一个Foo的类,在这个类里面实例了一个对象foo,它属于Foo类,通过原型链可以使用Foo原型链上的方法,也是一种常用的创建对象的方法。
这个方法看似像一个函数,但又有些不太一样。比如函数名一般都小写。如果学过其他面向对象的语言就会知道,这是类的写法(此处不多分析,非强制,但这么写有助于区分构造函数和
普通函数)。这种方法是构造函数创建对象的写法,通过构造函数创建对象,必须使用new 运算符。
构造函数可以创建对象执行的过程:
1)当使用了构造函数,并且new 构造函数(),那么就后台执行了new Object();
2)将构造函数的作用域给新对象,(即new Object()创建出的对象),而函数体内的this 就
代表new Object()出来的对象。
3)执行构造函数内的代码;
4)返回新对象(后台直接返回)。
注:
1)构造函数和普通函数的唯一区别,就是他们调用的方式不同。只不过,构造函数也是函数,必须用new 运算符来调用,否则就是普通函数。
2)this就是代表当前作用域对象的引用。如果在全局范围this 就代表window 对象,如果在构造函数体内,就代表当前的构造函数所声明的对象。
这种方法解决了函数识别问题,但消耗内存问题没有解决。同时又带来了一个新的问题,全局中的this 在对象调用的时候是Box 本身,而当作普通函数调用的时候,
this 又代表window。即this作用域的问题。
2、为什么在Foo上定义的原型方法,使用Foo调用不出来?
一个对象上的方法,可以是方法自身的方法,也可以是原型链上的方法。一般情况下的查找方式是先查找自身有没有getName方法,查找代码如下
Foo.getName();//此时查找的是Foo本身的方法,而此时Foo本身并未定义方法,所以沿着原型链往上查找。先找__proto__,发现指向Function.prototype。
在这依然没有找到,往下走寻找Function.prototype.__proto__,发现指向Object.prototype,再往后找到Oject.prototype.__proto__。沿着prototype原型
链寻找找不到这个方法后返回undefined。
Foo.prototype.getName();// 返回3,此时查找的是原型链上的方法,找到后按找方法返回3
foo.getName();// 此时先在foo对象本身的方法上查找,没有找到,然后到__proto__,查询到Foo.prototype并在上面发现getName方法。返回3。