因为 js 是解释执行的语言, 那么在代码中出现的函数与对象, 若是重复执行, 那么会建立多个副本, 消耗更多的内存, 从而下降性能java
function Foo( ... ){ this.name = name; this.age = age; this.sayHello = function(){ ... } }
new Foo()
建立出来的, 所以每个对象在建立的时候, 函数 sayHello 都会被建立一次function sayHello(){} function Foo(){ this.sayHello = sayHello; }
函数.prototype
引用, 这个特殊的对象是这个函数的原型属性var f1 = new Foo(); var f2 = new Foo(); f1.sayHello(); // 若是 f1 没有 sayHello, 那么就会在 Foo.prototype 中去找 f2.sayHello(); // 若是 f2 没有改方法, 那么就会在 Foo.prototype 中去找
function Foo() {} Foo.prototype.sayHello = function () { console.log( ... ); }; var f1 = new Foo(); f1.sayHello(); var f2 = new Foo(); f2.sayHello(); f1.sayHello === f2.sayHello
function Person() {} Person.prototype.name = '张三'; var p = new Person();
function Person() {} Person.prototype.name = '张三'; var p1 = new Person(); var p2 = new Person(); p1.name = '李四'; console.log( p1.name ); console.log( p2.name );
* 在传统的面向对象语言中( c, java ), 使用一个叫作类的东西定义模板, 而后使用模板建立对象 * 在构造方法中也具备相似功能, 叫作类
* 实例通常是指摸一个构造函数建立出来的对象, 叫作 XXX 构造函数的实例对象 * 实例就是对象, 对象是一个泛称 * 实例与对象是一个近义词
* 在 js 中, 键值对的集合被叫作对象 * 若是值为数据( 非函数 ), 就称该键值对为属性 property * 若是值为函数( 方法 ), 就称该键值对为方法 method
* 传统的面向对象的语言中使用类来实现继承, 那么就有父类, 子类 * 父类又称为基类, 子类有称为派生类 * 在 js 中, 经常被称为扶对象, 子对象, 基对象, 派生对象
* 原型对象就是构造函数的**原型属性** * 简称原型
* 原型对象相对于构造函数建立的实例对象称为**原型对象** * 简称原型
* 构造函数建立的实例对象 继承自 构造函数的原型属性( 构造函数.prototype ) * 构造函数建立的实例对象 继承自 该对象的原型对象 * 构造函数建立的实例对象与构造函数的原型属性表示的对象是两个不一样的对象 * 原型中的成员, 能够直接被实例对象调用 * 实例对象 "*含有*" 原型中的成员 * 实例对象 继承自 原型 * 这样的继承就是 "原型继承"
* 凡是对象都有构造函数 * {} => Object * [] => Array * /./ => Regexp * function... => Function
function Person() {} Person.prototype = { constructor: Person }; // 拆解 function Person() {} var o = {}; o.costructor = Person; // 属性中就存储着函数的地址 Person.prototype = o; Person = 123;
__proto__
属性, 来表示使用实例对象引用原型, 早期是非标准的__proto__
属性能够容许使用实例对象直接访问原型function Person() {} // 原型对象就是 Person.prototype // 那么只有使用 构造函数 才能够访问它 var o = new Person(); // 之前不能直接使用 o 来访问神秘对象 // 如今有了 __proto__ 后 // o.__proto__ 也能够直接访问原型对象( 两个下划线 ) // 那么 o.__proto__ === Person.prototype
constructor
, 构造器 , 将该原型和该原型的构造函数联系起来__proto__
的做用
var o = new Person(); o.constructor.prototype;
function Foo() {} Foo.prototype.name = 'test'; var o1 = new Foo(); var o2 = new Foo(); o1.name = '张三'; // 不是修改原型中的 name 而是本身增长了一个 name 属性 console.log( o1.name + ', ' + o2.name );
function Person(name){ this.name = name; } var P1 = new Person('Jim');