《JavaScipt高级程序设计》总结五

来源:互联网 发布:西昊 ergomax 知乎 编辑:程序博客网 时间:2024/05/02 04:25

对象:一组无序的属性集合,其属性可以包括基本值、对象或函数。对象的每个属性或方法都对应一个名字,而这个名字都映射到一个值。每个对象都是基于一个引用类型创建的。

var persion = new Object();     //创建一个Object实例person.name = "Grace";persopn.sayName = function() {    alert(this.name);}var person2 = {                  //对象字面量创建对象    name: "Grace",    sayName: function() {        alert(this.name);    }};function createPerson(name) {    //工厂模式    var o = new Object();            o.name = name;    o.sayname = function() {        alert(this.name);    };    return o;}createPerson("Gray");function Person(name) {         //构造函数模式    this.name = name;    this.sayName = function() {        alert(this.name);    }} var per = new Person("Gray");
  • 用new调用构造函数实际发生4个步骤:
    *创建一个新对象
    *将构造函数的作用域附给新对象(因此this就指向这个新对象)
    *执行构造函数中的代码(为这个对象添加属性)
    *返回这个对象
  • 将构造函数当作函数:
    *任何函数只要通过new操作符来调用,那么它就可以当作构造函数
    *不通过new操作符来调用,它跟普通函数没什么两样。属性和方法都被添加给window
  • 在构造函数中定义的函数可以移到构造函数外部来定义:
function per(name) {    this.name = name;    this.sayName = sayName;      //这样就不会每创建一个对象就创建一个新Function。因有this存在,所以执行代码前不用把函数绑定到特定对象上}function sayName() {    alert(this.name);}

我们创建的每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,而这个对象的用途可以包含由特定类型的所有实例共享的属性和方法
这里写图片描述
可以把对象共享的方法属性写在原型中,但是实例不能重写原型中的值。会屏蔽原型中保存的同名属性,阻止我们访问原型中的那个属性,但不会修改那个属性。

function Person() {};Person.prototype.name = "Grace";           var p1 = new Person();var p2 = new Person();p1.name = "Gray";alert(p1.name);           //Grayalert(p1.hasOwnProperty("name"));           //true --> 来自实例alert(p2.name);           //Gracedelete p1.name;alert(p1.name);           //Gracealert(p1.hasOwnProperty("name"));           //false --> 来自原型alert("name" in p1);      //true  --> 访问到给定的属性返回true,无论存在于实例还是原型中function hasPrototypeProperty(obj,name) {   //原型中的属性才返回true,实例中的属性或无此属性返回false    return !obj.hasOwnProperty(name) && (name in obj);}

由于原型中查找值得过程是一次搜索的,因此我们对原型对象所做的任何修改都能立即从实例上反映出来,即使先创建实例后修改原型。实例和原型之间的松散关系,在没有找到属性的情况下会继续搜索原型。因为实例和原型之间的连接只是一个指针而非副本。但是不能用字面量重写原型,因为这样会切断现有实例和新原型之间的联系。

继承
ECMAScript只支持实现继承,而且其实现继承主要依靠原型链来实现。其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。

function Parent() {    this.property = true;}Parent.prototype.getSubValue = function() {    return this.property;}function Child() {    this.childProperty = false;}//继承ParentChild.prototype = new Parent();var ins = new Child();alert(ins.getSubValue());      //true

原来存在于Parent实例的所有属性和方法,现在也存在于Child.prototype中了。因为我们没有使用Child默认提供的原型,而是给他换了一个新原型,这个新原型就是Parent的实例。
我们可以说ins是object,Parent,Child中任何一个类型的实例。
*子类型有时候要重写超类型中的某个方法或添加方法,给原型添加方法的代码一定要放在替换原型的语句之后。

因为原型链上的属性会被共享,为了解决自己问题,我们可以借用构造函数。在子类型构造函数内部调用超类型构造函数。因为函数只不过是在特定环境中执行代码的对象,因此通过使用apply()和call()方法也可以在新创建的对象上执行超类型的构造函数,初始化全部代码,那么每个子类型就会有自己的属性副本。

function Person() {    this.color = ['green','blue','red'];}function Child() {    Person.call(this);          //实现继承}var s1 = new Child();s1.push('yellow');alert(s1.color);               //green,blue,red,yellowvar s2= new Child();alert(s2.color);               //green,blue,red

但是在超类型的原型中定义的方法,对子类型而言也是不可见的,所以一般会采用组合继承。使用原型链实现对原型属性和方法的继承,而通过接通构造函数来实现对实力属性的继承。这样,即通过在原型上定义方法实现了函数的复用,又能够保证每个实例都要他自己的属性。

function Person(name) {    this.name = name;}Person.pototype.getName = function() {    alert(this.name);}function Child(age) {    Parent.call(this;                    //继承属性    this.age = age;};Child.prototype = new Parent();          //继承方法Child.prototype.constructor = Child;
0 0
原创粉丝点击