ECMAScriptJavaScript面向对象与原型

为了让属性和措施更好的反映封装的效用,并且收缩不须求的输入,原型的创始能够选用字面量的方式:

动态原型方式

寄生组合继承

就算我们能够透过对象实例访问保存在原型中的值,但却无法访问通过对象实例重写原型中的值。

in 操作符会在通过对象能够访问给定属性时回来
true,无论该属性存在于实例中仍然原型中。
alert(‘name’ in box); //true,存在实例中或原型中
咱们得以经过 hasOwnProperty()方法检查和测试属性是不是存在实例中,也足以因此 in
来判定实例或原型中是或不是存在属性。那么结合这两种办法,能够看清原型中是还是不是留存属性。

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

构造函数(构造方法):能够辨别对象

var box1 = new Box();
alert(box1.name); //Lee,原型里的值
box1.name = ‘Jack’;
alert(box.1name); //杰克,就近原则,
var box2 = new Box();
alert(box2.name); //Lee,原型里的值,没有被 box1 修改
假使想要 box1
也能在前边继续访问到原型里的值,能够把构造函数里的习性删除即可
,具体如下:
delete box1.name; //删除属性
alert(box1.name);
什么判定属性是在构造函数的实例里,依然在原型里?能够运用
hasOwnProperty()函数来证实:

1.函数名和实例化构造名相同且大写,(PS:非强制,但这么写有助于区分构造函数和平日函数);

原型(共享):创造的每一种函数都有多个prototype(原型)属性,那么些本性是四个对象,它的用途是富含能够由特定项目标有所实例共享的品质和章程。逻辑上得以那样精晓:prototype
通过调用构造函数而创办的十分目的的原型对象。使用原型的便宜能够让具有目的实例共享它所涵盖的属性和方法。也正是说,不必在构造函数中定义对象音信,而是能够直接将那一个音讯添加到原型中。

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

alert(box.hasOwnProperty(‘name’)); //实例里有重回 true,不然重回 false

安妥构造函数

ECMAScript 1ECMAScript 2

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() {}    //一时半刻新建3个构造函数,用来存款和储蓄传递进入的对象
  F.prototype = o;    //将o对象实例赋值给F构造的原型对象

在 JavaScript
里,被连续的函数称为超类型(父类,基类也行,别的语言叫法),继承的函数称为子类型(子类,派生类)。继承也有在此之前难点,比如字面量重写原型会中断关系,使用引用类型的原型,并且子类型还不可能给超类型传递参数。

原型对象不仅能够在自定义对象的意况下选拔,而 ECMAScript
内置的引用类型都足以运用那种措施,并且放置的引用类型作者也接纳了原型。

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

PS:使用动态原型格局,要留意一点,不可以再使用字面量的章程重写原型,因为会切断实例和新原型之间的联络。

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(‘杰克’, 200); //第①个实例
alert(box1.run());
alert(box2.run()); //保持独立

选拔构造函数创立原型对象和使用字面量成立对象在使用上基本相同,但要么有局地差别,字面量创立的主意选用constructor 属性不会针对实例,而会针对
Object,构造函数创制的法门则相反。

工厂形式:不可能分辨对象

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

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

2.由此构造函数创制对象,必须使用 new 运算符。

PS:就算给原生的嵌入引用类型丰硕方法应用起来尤其有利,但大家不引进应用那种办法。因为它恐怕会促成命名冲突,不方便人民群众代码维护。

__proto__天性:是实例指向原型对象的1个指针,它的职能就是指向构造函数的原型属性
constructor 。通过这四个属性,就足以访问到原型里的性质和方法了。

一而再:依靠原型链完结

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

原型方式的推行流程:
1.先查找构造函数实例里的属性或艺术,假设有,马上回到;
2.若是构造函数实例里没有,则去它的原型对象里找,假使有,就赶回;

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

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

ECMAScript 3

寄生构造函数

unction Box() {} //声美赞臣(Meadjohnson)个构造函数
Box.prototype.name = ‘Lee’; //在原型里添加属性
Box.prototype.age = 100;
Box.prototype.run = function () { //在原型里添加方法
  return this.name + this.age + ‘运行中…’;
};

exp:alert(Box.prototype.isPrototypeOf(box));
//只要实例化对象,即都会指向

判定1个对象是还是不是针对了该构造函数的原型对象,能够选用isPrototypeOf()方法来测试。

 ECMAScript 4

在原型形式申明中,多了三个属性,那多个属性都以创制对象时自动生成的。

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

如若想让字面量方式的 constructor 指向实例对象,那么能够那样做:
Box.prototype = {
  constructor : Box, //直接强制指向即可
};

对象冒充(伪造对象、经典两次三番、借用构造函数):消除引用共享和超类型不能传参的标题

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

PS:IE
浏览器在本子访问__proto__会无法分辨,火狐和谷歌浏览器及别的有个别浏览器均能鉴定识别。即使能够输出,但不可能获取内部信息。

function 博克斯(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);

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

  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); //引用难点一下子就解决了

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

整合继承:原型链+ 借用构造函数

 

构造函数的章程有部分正规:

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());