函数原型

原型链概要

Prototype属性是javascript为每个Function实例创建的一个对象。Prototype属性来自Function构造函数,Function构造函数为每个实例赋一个prootype属性

var myFunction = function() {};
console.log(myFunction.prototype);//输出myFunction{}
//默认的prototype属性是Object对象
console.log(typeof myFunction.prototype); //输出object

myFunction.prototype = {}; //设置prototype属性为空对象 console.log(myFunction.prototype);//输出空对象,object{}

原型链的最后是Object.prototype

例如:因为在myArray.foo,Array.prototype.foo,Object.prototype.foo中没有找到foo,所以foo是undefined,所以最后输出的是undefined

 var myArray = {};
console.log(myArray.foo);//输出undefined,

 

原型链返回在链中找到的第一个匹配结果

与作用域链一样,原型链在查找时将使用它找到的第一个值

查找的顺序为:自身对象----〉构造函数----〉Object对象

如下例子查找顺序为:myArray.foo->Array.prototype.fooàObject.prototype.foo

 Object.prototype.foo = "object-foo";
        Array.prototype.foo = "array-foo";
        var myArray = [];

        console.log(myArray.foo); //输出array-foo
        myArray.foo = "bar";
        console.log(myArray.foo);//输出bar 

用新对象替换prototype属性会删除默认函数属性

可以用一个新值来替换prototype属性的默认值,但是这样会删除原型对象中的默认得constructor属性,除非手动指定一个。

 var foo = function Foo() {
        };

        foo.prototype = {};
        var fooInstance = new foo();
        console.log(fooInstance.constructor === foo); //输出false,破坏了引用
        console.log(typeof fooInstance.constructor); //输出function
        foo.prototype = { constructor: foo }; //重新指定
        console.log(fooInstance.constructor === foo); //输出false,因为fooInstance在重新指定之前已经实例化,所以取不到最新值
        console.log(typeof fooInstance.constructor); //输出function
        var bar = new foo();
        console.log(bar.constructor === foo);//输出true
        console.log(typeof bar.constructor); //输出function

继承原型属性的实例总是能够获得最新值

实例总是能够从原型获得最新的值,不管何时被实例化,更改或附加,在这种意义上,prototype属性是动态的。

var foo = function Foo() { };
        foo.prototype.x = 1;
        var fooInstance = new foo();
        console.log(fooInstance.x);//输出1
        foo.prototype.x = 2;
        console.log(fooInstance.x);//输出2
        console.log(foo.x);//输出undefined

通过替换默认原型对象的方式赋值,例如:

var foo = function Foo() { };
        foo.prototype={x:1}
        var fooInstance = new foo();
        console.log(fooInstance.x);//输出1
        foo.prototype.x = 2;
        console.log(fooInstance.x);//输出2
        console.log(foo.x);//输出undefined

又例如:

var foo = function Foo() { };
        foo.prototype={x:1}
        var fooInstance = new foo();
        console.log(fooInstance.x);//输出1
        foo.prototype={x:2}
        console.log(fooInstance.x);//输出1,因为fooInstance对象在原型foo.prototype={x:2}之前,所以获取不到最新的原型值
        console.log(foo.x);//输出undefined

用新对象替换prototype属性不会更新以前的实例

创建一个实例时,该实例将在实例化时被绑定到“刚完成”的原型。

提供一个新对象做为prototype属性不会更新已创建实例和原型之间的连接。

例如:

var foo = function Foo() { };
        foo.prototype.x = 1;
        var fooInstance = new foo();
        console.log(fooInstance.x); //输出1
        //使用新Object()对象覆盖Foo的原型 
        foo.prototype = { x: 2 };
        console.log(fooInstance.x);//输出1,fooInstance依然是引用的初始化的原型对象
        
        //该新实例目前引用的就是新原型对象了(也就是{x:2})
        var newFoolInstance = new foo();
        console.log(newFoolInstance.x); //输出2

一旦开始创建实例,就不应用一个新对象来替换对象的原型

 

用户自定义构造函数像原生构造函数一样原型继承

//用户自定义构造函数像原生构造函数一样原型继承
        var Person = function() {
        };
        Person.prototype.legs = 2;
        Person.prototype.arms = 2;
        Person.prototype.countLimbs = function() {
            return this.legs + this.arms;
        };
        var chuck = new Person();
        console.log(chuck.countLimbs());//输出4


  //为了很好的展示原型链,可以创建一个构造函数,通过给构造函数传值,而覆盖原型的值
        var Person = function(legs, arms) {
            //隐藏原型的值
            if (legs != undefined) {
                this.legs = legs;
            }
            if (arms != undefined) {
                this.arms = arms;
            }
        };
        Person.prototype.legs = 2;
        Person.prototype.arms = 2;
        Person.prototype.countLimbs = function() {
            return this.legs + this.arms;
        };
        var chuck = new Person(0, 0);
        console.log(chuck.countLimbs());//输出0

 

创建继承链

只需 要将对象实例做为要继承该对象实例的函数的prototype的属性值

例如:chef对象需要继承Person(),只需要将chef.prototype指向实例化的Person()

即:chef.prototype=new Person();

//创建继承链
        var Person = function() {
            this.bar = 'bar';
        };
        Person.prototype.foo = "foo";

        var chef = function() {
            this.goo = "goo";
        };

        chef.prototype = new Person(); //创建继承
        var cody = new chef();
        console.log(cody.foo); //输出foo
        console.log(cody.goo); //输出goo
        console.log(cody.bar);//输出bar

 

posted on 2016-02-23 18:30  Alice.Luo  阅读(578)  评论(0编辑  收藏  举报