ECMAScriptJavaScript面向对象与原型

工厂模式:无法分辨对象

function createObject(name, age) { //集中实例化的函数
  var obj = new Object();
  obj.name = name;
  obj.age = age;
  obj.run = function () {
    return this.name + this.age + ‘运行中…’;
  };
  return obj;
}
var box1 = createObject(‘Lee’, 100); //第一个实例
var box2 = createObject(‘Jack’, 200); //第二独实例
alert(box1.run());
alert(box2.run()); //保持独立

alert(typeof box1); //Object
alert(box1 instanceof Object); //true

构造函数(构造方法):可以分辨对象

function Box(name, age) { //构造函数模式
  this.name = name;
  this.age = age;
  this.run = function () {
    return this.name + this.age + ‘运行中…’;
  };
}
var box1 = new Box(‘Lee’, 100); //new Box()即可
var box2 = new Box(‘Jack’, 200);

alert(box1.run());
alert(box1 instanceof Box); //很清晰的辨识他起属于 Box

构造函数的道发生部分正式:

1.函反复曰以及实例化构造名相同且颇写,(PS:非强制,但如此写有助于区分构造函数和通常函数);

2.经构造函数创建对象,必须运用 new 运算符。

var o = new Object();
Box.call(o, ‘Jack’, 200) //对象冒充调用
alert(o.run());

原型(共享):创建的每个函数都出一个
prototype(原型)属性,这个特性是一个靶,它的用处是富含可以由特定项目的备实例共享的性质和办法。逻辑上得以这样理解:prototype
通过调用构造函数而创造的不行目标的原型对象。使用原型的功利可以吃具有目标实例共享它所涵盖的性与章程。也就是说,不必在构造函数中定义对象信息,而是可以一直以这些信补充加至原型中。

unction Box() {} //声明一个构造函数
Box.prototype.name = ‘Lee’; //在原型里上加属性
Box.prototype.age = 100;
Box.prototype.run = function () { //在原型里补充加方
  return this.name + this.age + ‘运行中…’;
};

ECMAScript 1ECMAScript 2

当原型模式声明遭,多矣区区个特性,这半单特性都是创建对象时自动生成的。

__proto__特性:是实例指向原型对象的一个指针,它的作用就是依为构造函数的原型属性
constructor 。通过这点儿独特性,就足以看到原型里的特性和方了。

PS:IE
浏览器在本子访问__proto__会无能够辨识,火狐和谷歌浏览器与其余一些浏览器都能辨识。虽然好出口,但无法取内部消息。

认清一个对象是否对准了拖欠构造函数的原型对象,可以用
isPrototypeOf()方法来测试。

exp:alert(Box.prototype.isPrototypeOf(box));
//只要实例化对象,即都见面针对

原型模式之实施流程:
1.先查找构造函数实例里之属性或艺术,如果发,立刻回去;
2.如构造函数实例里没有,则去她的原型对象里寻找,如果产生,就返回;

虽说咱得以经过对象实例访问保存在原型中之价值,但可非克顾通过对象实例更写原型中之价值。

var box1 = new Box();
alert(box1.name); //Lee,原型里之价
box1.name = ‘Jack’;
alert(box.1name); //Jack,就近原则,
var box2 = new Box();
alert(box2.name); //Lee,原型里之价值,没有吃 box1 修改
假使想要 box1
啊会以后面继续看到原型里的价,可以拿构造函数里的习性删除即可
,具体如下:
delete box1.name; //删除属性
alert(box1.name);
哪判定属性是于构造函数的实例里,还是以原型里?可以应用
hasOwnProperty()函数来说明:

alert(box.hasOwnProperty(‘name’)); //实例里有归 true,否则回 false

 ECMAScript 3

in 操作符会在经过对象能够访问给定属性时返回
true,无论该属性在被实例中尚是原型中。
alert(‘name’ in box); //true,存在实例中还是原型中
咱得经 hasOwnProperty()方法检测属性是否留存实例中,也堪经 in
来判定实例或原型中是否留存属性。那么做这有限种办法,可以判断原型中是否存在属性。

function isProperty(object, property) { //判断原型中是不是在属性
  return !object.hasOwnProperty(property) && (property in object);
}

var box = new Box();
alert(isProperty(box, ‘name’)) //true,如果原型有

为为性与艺术重新好之反映封装的效用,并且减少非必要的输入,原型的创造好运用字面量的办法:

function Box() {};
Box.prototype = { //使用字面量的法门
  name : ‘Lee’,
  age : 100,
  run : function () {
    return this.name + this.age + ‘运行中…’;
  }
};

使构造函数创建原型对象同下字面量创建对象在采取上基本相同,但要产生部分分别,字面量创建的办法下
constructor 属性不见面对实例,而会针对
Object,构造函数创建的法尽管反。

万一想被许面量方式的 constructor 指向实例对象,那么好如此做:
Box.prototype = {
  constructor : Box, //直接强制指向即可
};

原型对象不仅可以以自定义对象的情景下行使,而 ECMAScript
内置的援类型且足以利用这种艺术,并且放置的援类型我也以了原型。

alert(Array.prototype.sort); //sort 就是 Array 类型的原型方法
alert(String.prototype.substring); //substring 就是 String
类型的原型方法
String.prototype.addstring = function () { //给 String
类型添加一个道
  return this + ‘,被填补加了!’; //this 代表调用的字符串
};
alert(‘Lee’.addstring()); //使用这个法

PS:尽管为原生的放置引用类型丰富方法应用起来特别有益,但我们无引进使用这种办法。因为她或许会见促成命名冲突,不便利代码维护。

动态原型模式

function Box(name ,age) { //将所有消息打包到函数体内
  this.name = name;
  this.age = age;
  if (typeof this.run != ‘function’) { //仅在首先次调用的初始化
    Box.prototype.run = function () {
      return this.name + this.age + ‘运行中…’;
    };
  }
}
var box = new Box(‘Lee’, 100);
alert(box.run());

PS:使用动态原型模式,要小心一点,不得以更使用字面量的法门重写原型,因为会切断实例和初原型之间的维系。

寄生构造函数

function Box(name, age) {
  var obj = new Object();
  obj.name = name;
  obj.age = age;
  obj.run = function () {
    return this.name + this.age + ‘运行中…’;
  };
  return obj;
}

妥善构造函数

function Box(name , age) {
  var obj = new Object();
  obj.run = function () {
    return name + age + ‘运行中…’; //直接打印参数即可
  };
  return obj;
}
var box = Box(‘Lee’, 100); //直接调用函数
alert(box.run());

继往开来:依靠原型链完成

function Box() { //Box 构造
  this.name = ‘Lee’;
}
function Desk() { //Desk 构造
  this.age = 100;
}
Desk.prototype = new Box(); //Desc 继承了 Box,通过原型,形成链条
var desk = new Desk();
alert(desk.age);
alert(desk.name); //得到给接续的习性
function Table() { //Table 构造
  this.level = ‘AAAAA’;
}
Table.prototype = new Desk(); //继续原型链继承
var table = new Table();
alert(table.name); //继承了 Box 和 Desk

ECMAScript 4

每当 JavaScript
里,被延续的函数称为超类型(父类,基类也实施,其他语言叫法),继承的函数称为子类型(子类,派生类)。继承也生前问题,比如字面量重写原型会中断关系,使用引用类型的原型,并且子类型还无法为超类型传递参数。

目标冒充(伪造对象、经典延续、借用构造函数):解决引用共享和超类型无法传参的题目

function Box(age) {
  this.name = [‘Lee’, ‘Jack’, ‘Hello’]
  this.age = age;
}
function Desk(age) {
  Box.call(this, age); //对象冒充,给超类型传参

}
var desk = new Desk(200);
alert(desk.age);
alert(desk.name);
desk.name.push(‘AAA’); //添加的初数据,只被 desk
alert(desk.name);

结缘继承:原型链+ 借用构造函数

function Box(age) {
  this.name = [‘Lee’, ‘Jack’, ‘Hello’]
  this.age = age;
}
Box.prototype.run = function () {
  return this.name + this.age;
};
function Desk(age) {
  Box.call(this, age); //对象冒充
}
Desk.prototype = new Box(); //原型链继承
var desk = new Desk(100);
alert(desk.run());

寄生组合继承

function obj(o) {     //传递一个字面量函数
  function F() {}    //临时新建一个构造函数,用来囤积传递进入的靶子
  F.prototype = o;    //将o对象实例赋值给F构造的原型对象

  return new F();    //返回实例化后底构造函数
}
function create(box, desk) {
  var f = obj(box.prototype);
  f.constructor = desk;
  desk.prototype = f;
}
function Box(name) {
  this.name = name;
  this.arr = [‘哥哥’,’妹妹’,’父母’];
}
Box.prototype.run = function () {
  return this.name;
};
function Desk(name, age) {
  Box.call(this, name);
  this.age = age;
}
inPrototype(Box, Desk); //通过这里实现连续
var desk = new Desk(‘Lee’,100);
desk.arr.push(‘姐姐’);
alert(desk.arr);
alert(desk.run()); //只共享了点子
var desk2 = new Desk(‘Jack’, 200);
alert(desk2.arr); //引用问题迎刃而解