JavaScript面向对象与原型

工厂模式:无法识别对象

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 + ‘运行中...‘;
};

在原型模式声明中,多了两个属性,这两个属性都是创建对象时自动生成的。

__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

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

在 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); //引用问题解决

时间: 2024-08-06 11:32:41

JavaScript面向对象与原型的相关文章

第一百零九节,JavaScript面向对象与原型

JavaScript面向对象与原型 学习要点: 1.学习条件 2.创建对象 3.原型 4.继承 ECMAScript有两种开发模式:1.函数式(过程化),2.面向对象(OOP).面向对象的语言有一个标志,那就是类的概念,而通过类可以创建任意多个具有相同属性和方法的对象.但是,ECMAScript没有类的概念,因此它的对象也与基于类的语言中的对象有所不同.   一.学习条件 在JavaScript视频课程第一节课,就已经声明过,JavaScript课程需要大量的基础.这里,我们再详细探讨一下: 1

JavaScript 面向对象 (prototype 原型模式)

一. JavaScript 设计思想 1994年,网景公司(Netscape)发布了Navigator浏览器0.9版.这是历史上第一个比较成熟的网络浏览器,轰动一时.但是,这个版本的浏览器只能用来浏览,不具备与访问者互动的能力.比如,如果网页上有一栏"用户名"要求填写,浏览器就无法判断访问者是否真的填写了,只有让服务器端判断.如果没有填写,服务器端就返回错误,要求用户重新填写,这太浪费时间和服务器资源了. 因此,网景公司急需一种网页脚本语言,使得浏览器可以与网页互动.工程师_Brend

JavaScript面向对象与原型(一):构造函数

提到构造函数,我们并不陌生,在面向对象领域,构造函数已经是一个老生常谈的问题了.在JavaScript中再次学习,真的是有一种亲切的感觉. 一.简单回顾 构造函数 ,是一种特殊的方法 .主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中.特别的一个类可以有多个构造函数,可根据其参数个数的不同或参数类型的不同来区分它们即构造函数的重载. C#构造函数(一个简单的小例子): <span style="font-size:14px;"

有关javaScript面向对象和原型笔记

javaScript是一种比較特殊的语言,ECMAScript中没有类的概念.跟其它面向对象的语言有一定的差别.它的对象也与基于类的语言中的对象有所不同,严格来说,javascript对象是一组没有特定顺序的值,对象的每一个属性或方法都有一个名字.而每一个名字都映射到一个值.每一个对象都是基于一个引用类型的创建的. 创建自己定义对象的最简单的方式就是创建一个Object的实例.然后再为其加入属性和方法,如: var box = new Object(); //创建对象 box.name1 = '

javascript面向对象和原型

/* //工厂模式 function createObject(name,age){ var obj = new Object();//新建一个对象 obj.name=name;//新建对象的属性 obj.age=age; obj.run=function(){//新建对象的方法 return this.name+","+this.age+"...running."; } return obj;//返回新建的对象引用 } var box1 = createObjec

JavaScript 面向对象与原型

ECMAScript有两种开发模式:1.函数式(过程化);2.面向对象(OOP); 一 创建对象1.普通的创建对象 ? 1 2 3 4 5 6 7 8 9 // 创建一个对象,然后给这个对象新的属性和方法;   var box = new Object();       // 创建一个Object对象;   box.name = 'lee';          // 创建一个name属性并赋值;   box.age = 100;   box.run = function(){        //

JavaScript面向对象和原型函数

对象,是javascript中非常重要的一个梗,是否能透彻的理解它直接关系到你对整个javascript体系的基础理解,说白了,javascript就是一群对象在搅..(哔!). 常用的几种对象创建模式 使用new关键字创建 最基础的对象创建方式,无非就是和其他多数语言一样说的一样:没对象,你new一个呀! var gf = new Object(); gf.name = "tangwei"; gf.bar = "c++"; gf.sayWhat = functio

快速理解JavaScript面向对象编程—原型继承

总的来说js语言就是门面向对象编程的语言,对象这个概念几乎贯穿了整个js的学习. 对象 创建对象两种方法:(若要生成对象实例必须调用构造函数) 1.var obj = {name:"jer" , age:12};(在js内部调用了预设的Object()构造函数) 访问:alert(obj.name);//"jer" alert(obj["name"]);//"jer" 2.var obj = new Object(); obj

javascript面向对象和原型————呱呱二号

面向对象 1.工厂模式 function createObject(name,age){ let obj = new Object(); this.name = name; this.age = age; return obj; } let objA = createObject('Tom',24); let objB = createObject('Jane',23); typeof ObjA; //Object typeof ObjB; //Object ObjA instanceof Ob