比方在函数中利用this,则this指代怎么是根据运行时此函数在如何目的上被调用

一、经典的连续方式

[Douglas Crockford]
http://javascript.crockford.com/prototypal.html
http://javascript.crockford.com/inheritance.html
[John Resig]
http://ejohn.org/blog/simple-javascript-inheritance/
[Dean Edwards]
http://dean.edwards.name/weblog/2006/03/base/
[prototype]
http://www.prototypejs.org/learn/class-inheritance
[Mootools]
http://mootools.net/core/docs/1.5.1/Class/Class

js老调重弹之this,constructor ,prototype全面剖析,prototype周全剖析

前言

javascript中的this,constructor
,prototype,都是新瓶装旧酒的题材,长远理解他们的意义至关心注重要。在此处,大家再来复习一下啊,温故而知新!

this

this表示近来目标,即便在大局意义范围内利用this,则代表当前页面对象window;
若是在函数中选取this,则this指代什么是依据运转时此函数在怎样指标上被调用。
大家还足以应用apply和call多个全局方法来改变函数中this的求实针对。

先看1个在全局意义范围内选用this的例子:

console.log(this === window); // true
console.log(window.alert === this.alert); // true
console.log(this.parseInt("021", 10)); // 10

函数中的this是在运营时间控制制的,而不是函数定义时,如下:

// 定义一个全局函数
    function foo() {
      console.log(this.fruit);
    }
    // 定义一个全局变量,等价于window.fruit = "apple";
    var fruit = "apple";
    // 此时函数foo中this指向window对象
    // 这种调用方式和window.foo();是完全等价的
    foo(); // "apple"

    // 自定义一个对象,并将此对象的属性foo指向全局函数foo
    var pack = {
      fruit: "orange",
      foo: foo
    };
    // 此时函数foo中this指向window.pack对象
    pack.foo(); // "orange"

全局函数apply和call能够用来改变函数中this的对准,如下:

// 定义一个全局函数
    function foo() {
      console.log(this.fruit);
    }

    // 定义一个全局变量
    var fruit = "apple";
    // 自定义一个对象
    var pack = {
      fruit: "orange"
    };

    // 等价于window.foo();
    foo.apply(window); // "apple"
    // 此时foo中的this === pack
    foo.apply(pack);  // "orange"

注:apply和call五个函数的功效壹样,唯1的差别是四个函数的参数定义分歧。

因为在JavaScript中等高校函授数也是目的,所以大家能够看到如下有趣的例证:

// 定义一个全局函数
    function foo() {
      if (this === window) {
        console.log("this is window.");
      }
    }

    // 函数foo也是对象,所以可以定义foo的属性boo为一个函数
    foo.boo = function() {
      if (this === foo) {
        console.log("this is foo.");
      } else if (this === window) {
        console.log("this is window.");
      }
    };
    // 等价于window.foo();
    foo(); // this is window.

    // 可以看到函数中this的指向调用函数的对象
    foo.boo(); // this is foo.

    // 使用apply改变函数中this的指向
    foo.boo.apply(window); // this is window.

prototype

prototype本质上依然1个JavaScript对象。

与此同时每一种函数都有1个暗中认可的prototype属性。
假设这么些函数被用在创立自定义对象的情景中,大家称这几个函数为构造函数。
比如下边三个不难易行的光景:

// 构造函数
    function Person(name) {
      this.name = name;
    }
    // 定义Person的原型,原型中的属性可以被自定义对象引用
    Person.prototype = {
      getName: function() {
        return this.name;
      }
    }
    var hao= new Person("haorooms");
    console.log(hao.getName());  // "haorooms"

用作类比,大家怀想下JavaScript中的数据类型 –
字符串(String)、数字(Number)、数组(Array)、对象(Object)、日期(Date)等。

大家有理由相信,在JavaScript内部那个体系都是当做构造函数来达成的,比如:

// 定义数组的构造函数,作为JavaScript的一种预定义类型
    function Array() {
      // ...
    }

    // 初始化数组的实例
    var arr1 = new Array(1, 56, 34, 12);
    // 但是,我们更倾向于如下的语法定义:
    var arr2 = [1, 56, 34, 12];

还要对数组操作的广大措施(比如concat、join、push)应该也是在prototype属性中定义的。
实际上,JavaScript全体的固有数据类型都享有只读的prototype属性
(那是能够领略的:因为只要改动了那几个项目标prototype属性,则什么预约义的办法就没有了),
可是大家得以向里面添加本人的恢宏方法。

// 向JavaScript固有类型Array扩展一个获取最小值的方法
    Array.prototype.min = function() {
      var min = this[0];
      for (var i = 1; i < this.length; i++) {
        if (this[i] < min) {
          min = this[i];
        }
      }
      return min;
    };

    // 在任意Array的实例上调用min方法
    console.log([1, 56, 34, 12].min()); // 1

在意:那里有2个圈套,向Array的原型中添加扩大方法后,当使用for-in循环数组时,这么些扩充方法也会被循环出来。
上边包车型大巴代码表明这点(借使已经向Array的原型中扩充了min方法):

var arr = [1, 56, 34, 12];
    var total = 0;
    for (var i in arr) {
      total += parseInt(arr[i], 10);
    }
    console.log(total);  // NaN

竭泽而渔办法也很简短:

var arr = [1, 56, 34, 12];
    var total = 0;
    for (var i in arr) {
      if (arr.hasOwnProperty(i)) {
        total += parseInt(arr[i], 10);
      }
    }
    console.log(total);  // 103

constructor

constructor始终对准成立当前指标的构造函数。比如下边例子:

// 等价于 var foo = new Array(1, 56, 34, 12);
    var arr = [1, 56, 34, 12];
    console.log(arr.constructor === Array); // true
    // 等价于 var foo = new Function();
    var Foo = function() { };
    console.log(Foo.constructor === Function); // true
    // 由构造函数实例化一个obj对象
    var obj = new Foo();
    console.log(obj.constructor === Foo); // true

    // 将上面两段代码合起来,就得到下面的结论
    console.log(obj.constructor.constructor === Function); // true

然则当constructor境遇prototype时,逸事体就产生了。
大家知道种种函数都有3个默许的属性prototype,而以此prototype的constructor暗中认可指向那几个函数。如下例所示:

function Person(name) {
      this.name = name;
    };
    Person.prototype.getName = function() {
      return this.name;
    };
    var p = new Person("haorooms");

    console.log(p.constructor === Person); // true
    console.log(Person.prototype.constructor === Person); // true
    // 将上两行代码合并就得到如下结果
    console.log(p.constructor.prototype.constructor === Person); // true

旋即当大家再一次定义函数的prototype时(注意:和上例的差距,那里不是修改而是覆盖),
constructor的行事就有点奇怪了,如下示例:

function Person(name) {
      this.name = name;
    };
    Person.prototype = {
      getName: function() {
        return this.name;
      }
    };
    var p = new Person("haorooms");
    console.log(p.constructor === Person); // false
    console.log(Person.prototype.constructor === Person); // false
    console.log(p.constructor.prototype.constructor === Person); // false

缘何吧? 原来是因为覆盖Person.prototype时,等价于进行如下代码操作:

Person.prototype = new Object({
      getName: function() {
        return this.name;
      }
    });

而constructor始终本着创立自身的构造函数,所以那时候Person.prototype.constructor
=== Object,便是:

function Person(name) {
      this.name = name;
    };
    Person.prototype = {
      getName: function() {
        return this.name;
      }
    };
    var p = new Person("haorooms");
    console.log(p.constructor === Object); // true
    console.log(Person.prototype.constructor === Object); // true
    console.log(p.constructor.prototype.constructor === Object); // true

怎么校正那种问题呢?方法也很简短,重新覆盖Person.prototype.constructor即可:

function Person(name) {
      this.name = name;
    };
    Person.prototype = {
      getName: function() {
        return this.name;
      }
    };
    Person.prototype.constructor = Person;
    var p = new Person("haorooms");
    console.log(p.constructor === Person); // true
    console.log(Person.prototype.constructor === Person); // true
    console.log(p.constructor.prototype.constructor === Person); // true

也得以这么写:

function Person(name) {
      this.name = name;
    };
    Person.prototype = {
     constructor:Person,//指定constructor
      getName: function() {
        return this.name;
      }
    };

如上那篇js沉滓泛起之this,constructor
,prototype周密剖析正是小编分享给大家的全体内容了,希望能给大家四个参阅,也指望我们多多帮忙帮客之家。

http://www.bkjia.com/Javascript/1116446.htmlwww.bkjia.comtruehttp://www.bkjia.com/Javascript/1116446.htmlTechArticlejs老生常谈之this,constructor
,prototype周密剖析,prototype全面解析 前言
javascript中的this,constructor
,prototype,都是老生常谈的题材,深远精通她们…

二、this、constructor、prototype

2.1 this

this代表近年来目的,尽管在全局范围内使用this,则代表当前页面对象window;要是在函数中应用this,则this指代怎么样是依照运营时此函数在怎么样指标上被调用。

【注意】:函数中的this是在运作时间控制制的,而不是函数定义时。

call和apply能够用来改变函数中this的对准。

function foo() {
    console.log(this.fruit);
}

var fruit = "apple";
var obj = {
    fruit: "orange"
};

foo.apply(window); // "apple"
foo.apply(obj); // "orange"

【注意】:
call和apply的效益一样,唯一的差别是四个函数的参数不一致。

2.2 prototype

2.3 constructor

constructor始终对准创制当前指标的构造函数。例如下边包车型客车例子:

var arr = [1, 56, 34, 12];
console.log(arr.constructor === Array); // true

// 等价于 var foo = new Function();
var Foo = function() { };
console.log(Foo.constructor === Function); // true

// 由构造函数实例化一个obj对象
var obj = new Foo();
console.log(obj.constructor === Foo); // true

// 将上面两段代码合起来,就得到下面的结论
console.log(obj.constructor.constructor === Function); // true

可是当constructor遭逢prototype时,有趣的作业就发生了。
笔者们掌握各种函数都有三个暗中同意的属性prototype,而这几个prototype的constructor暗中同意指向那个函数。如下例所示:

function Person(name) {
    this.name = name;
};
Person.prototype.getName = function() {
    return this.name;
};
var p = new Person("ZhangSan");

console.log(p.constructor === Person); // true
console.log(Person.prototype.constructor === Person); // true
// 将上两行代码合并就得到如下结果
console.log(p.constructor.prototype.constructor === Person); // true

当下当我们再一次定义函数的prototype时(注意:和上例的差异,这里不是修改而是覆盖),
constructor的表现就有点奇怪了,如下示例:

function Person(name) {
    this.name = name;
};
Person.prototype = {
    getName: function() {
        return this.name;
    }
};
var p = new Person("ZhangSan");
console.log(p.constructor === Person); // false
console.log(Person.prototype.constructor === Person); // false
console.log(p.constructor.prototype.constructor === Person); // false

缘何吧?
原先是因为覆盖Person.prototype时,等价于进行如下代码操作:

Person.prototype = new Object({
    getName: function() {
        return this.name;
    }
});

而constructor始终本着创造本身的构造函数,所以此时Person.prototype.constructor
=== Object,正是:

function Person(name) {
    this.name = name;
};
Person.prototype = {
    getName: function() {
        return this.name;
    }
};
var p = new Person("ZhangSan");
console.log(p.constructor === Object); // true
console.log(Person.prototype.constructor === Object); // true
console.log(p.constructor.prototype.constructor === Object); // true

怎么考订那种题材吧?方法也很简单,重新覆盖Person.prototype.constructor即可:

function Person(name) {
    this.name = name;
};
Person.prototype = new Object({
    getName: function() {
        return this.name;
    }
});
Person.prototype.constructor = Person;
var p = new Person("ZhangSan");
console.log(p.constructor === Person); // true
console.log(Person.prototype.constructor === Person); // true
console.log(p.constructor.prototype.constructor === Person); // true