有下列例子
- function Foo() {}
- Foo.prototype.getName = function () {
- alert(3);
- };
- var foo = new Foo();
- foo.getName();// 3;
- Foo.getName();// Foo.getName is not a function
问题:
1var 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
来源: https://www.2cto.com/kf/201802/724630.html