JavaScript

彻底搞清javascript中this, constructor

2017-01-09  本文已影响39人  已过云烟

说起这三个属性,肯定有一些同学和我一样,初学js时非常困惑,头大,一脸的迷茫。今天就来给大家彻底解决这些担心受怕的问题。

先看this

this定义:

this就是函数赖以执行的对象。

分析这句话:

1. this是对象。

2. this依赖函数执行的上下文环境。

3. this存在函数中。

直接看例子:

alert(this); //在全局环境调用this, this指向window,  输出[Object window]

function Person(){

     alert(this);

}

方式一:

Person(); // 全局环境用Person函数, this指向window,  输出[Object window]

方式二:

var obj = new Person(); //把Person当做构造函数, 实例化一个对象

//此时this指向了obj, 不再指向window,  输出[Object object]

function Person(){

     alert(this.name); //此时无法判断this的身份

}

Person(); //this在全局环境中被调用, this.name == window.name, 输出了窗口的名字

var obj = new Person(); //this在obj环境下被调用, this.name == obj.name, 由于name没被赋值, 所以输出undefined

由此可以看出, 我们在阅读代码或者写代码时,看到某个函数中定义的this时, 还无法去判断那个this身份,必须找到它依赖执行的环境(对象)。

再回头看看this的定义,大家就清楚自然了。

再看constructor和prototype

constructor和prototype的关系非常密切。

constructor是一个对象的属性,这个属性存在在此对象的prototype中, 指向此对象的构造函数。

分析这句话:

1.constructor是一个对象属性。

2.constructor在prototype中

3.constructor指向构造函数

例子1:

function Person(name, age){

      this.name = name;

      this.age = age;

}

Person.prototype.getName = function(){

     alert(this.name);

}

Person.prototype.getAge = function(){

     alert(this.age);

}

var obj = new Person();

alert(obj.constructor == Person);// true

此种方式定义的prototype, constructor是隐藏的, 默认指向Person

例子2:

function Person(name, age){

     this.name = name;

     this.age = age;

}

Person.prototype = {

     getName: function(){

         alert(this.name);

 },

getAge: function(){

         alert(this.age);

   }

}

var obj = new Person();

alert(obj.constructor == Person);// false

为什么是false? 这种定义prototype, 是把prototype重写了, 覆盖了默认的constructor。

换句话说, 其实这种方式就是给属性重新赋值了, 所以导致默认的constructor被覆盖。

此时的obj.constructor将指向的是Object。

改写一下上面的:

Person.prototype = {

      constructor: Person, //强制指向Person

       getName: function(){

            alert(this.name);

      },

    getAge: function(){

        alert(this.age);

    }

}

此时constructor就指向Person了。

prototype是一个函数属性, 此属性同时也是一个对象, 保存着对象实例所共有的属性和方法。

分析这句话:

1.prototype是函数属性, 只要是函数, 就有prototype属性. 而不管是构造函数还是普通函数.

2.prototype同时也是对象.

2.prototype放的是公共的东西, 包括属性和方法.

例子1.

function Person(name, age){

      this.name = name;

      this.age = age;

}

//是函数就有prototype属性, 这个属性也是一个对象

Person.prototype = {

     getName: function(){ //所有对象实例都共享

     return this.name;

  },

  getAge: function(){//所有对象实例都共享

      return this.age;

  }

}

var obj = new Person('tom', 23);

obj.getName(); //'tom'

var obj2 = new Person('jack', 23);

obj2.getName(); //'jack'

obj.getName == obj2.getName; //true, 所有实例共享

Person.prototype.getName(); //当做普通函数属性, 根据this定义, 此时this指向的是Person.prototype, 所以返回undefined

以上就是this, constructor, prototype的定义和他们之间的关系. 可能还有些粗糙, 欢迎大家补充.

综合例子:

var Tinker = function(){

       this.elements = [];

};

Tinker.fn = Tinker.prototype = {

       constructor: Tinker,

       extend: function(obj){

             var p;

           for(p in obj){

              this.constructor.prototype[p] = obj[p];//此处若看明白了, 那么前面的就理解了

       }

     }

}

Tinker.fn.extend({

get: function(){

     var length = arguments.length,

            i = 0;

       for(; i < length; i++){

          this.elements.push(document.getElementById(arguments[i])); //此处若看明白了, 那么前面的就理解了

     }

      return this;//此处若看明白了, 那么前面的就理解了

},

each: function(fn){

      var i = 0,

         length = this.elements.length;

       for(; i < length; i++){

         fn.call(this.elements[i], i, this.elements[i]);

      }

      return this;//此处若看明白了, 那么前面的就理解了

   }

});

这个例子其实很简单, 就是向一个对象原型添加方法.一个方法是get, 用于查找页面id. 一个是each, 用于对找到的id元素执行一个方法

//假设有id = 'data', id = 'message'

var obj = new Tinker();

obj.get('data', 'message').each(function(i, item){

     this.style.cssText = 'height:20px; background:#ff0000';

})

上一篇 下一篇

猜你喜欢

热点阅读