JavaScript 高级特性

1. 原型Prototype

1.1 构造函数

  所谓"构造函数",其实就是一个普通函数,可是内部使用了this变量。对构造函数使用new运算符,就能生成实例,而且this变量会绑定在实例对象上。  javascript

 

function Cat(name, color) {
    this.name = name;
    this.color = color;
}

var cat1 = new Cat("大毛", "黄色");
var cat2 = new Cat("二毛", "黑色");
alert(cat1.name); // 大毛
alert(cat1.color); // 黄色

//这时cat1和cat2会自动含有一个constructor属性,指向它们的构造函数。
cat1.constructor == Cat; //true
cat2.constructor == Cat; //true

function Cat(name, color) {
    this.name = name;
    this.color = color;
    this.type = "猫科动物";
    this.eat = function () { alert("吃老鼠"); };
}

cat1.type; // 猫科动物
cat1.eat(); // 吃老鼠
//每个实例对象,每一次生成重复内容内存,可是内存地址不同
cat1.eat == cat2.eat; //false

 

1.2 实例.constructor

  每一个构造函数生成实例的时候 会自带一个constructor属性 指向该构造函数。对于普通对象生成实例时,constructor指向其类型的构造函数。html

  结论1: 实例.constructor == 构造函数java

function Cat(name) {
    this.name = name;
}
var cat1 = new Cat("大毛");
cat1.constructor == Cat; //true

var str1 = "123";
str1.constructor == String;//true

 

1.3 实例.prototype

  构造函数都有一个prototype属性,指向另外一个对象。这个对象的全部属性和方法,都会被构造函数的实例继承浏览器

  对该构造函数的实例,继承的prototype对象都指向同一个。    闭包

  结论2: 实例1.prototype.func == 实例2.prototype.func函数

function Cat(name, color) {
    this.name = name;
    this.color = color;
}
Cat.prototype.type = "猫科动物";
Cat.prototype.eat = function () { alert("吃老鼠") };

cat1.eat == cat2.eat;//true
// hasOwnProperty判断是本身自己的属性仍是继承的
cat1.hasOwnProperty("name"); //true
cat1.hasOwnProperty("type"); //false

 

1.4 实例.__proto__ 

  Javascript建立对象时(普通对象和函数对象),都会内置一个__proto__属性,指向 实例的建立函数(实例.constructor).prototypethis

  结论3: 实例.__proto__ === 构造函数.prototype spa

  同理: 构造函数.prototype.__proto__ === Object.prototype prototype

 

2. 做用域Scope

2.1 全局变量

  全局声明的变量,浏览器环境实际上声明在顶层变量"window"下。指针

  函数内部声明变量时,未使用var关键字,会声明为全局变量。  

function f1() {
    n = 999;
}
f1();//调用函数时,n被注册到全局
alert(n); // 999
alert(window.n); // 999

  

2.2 局部变量

  只能在局部使用并可见的变量,如函数内部声明的变量  

function f2() {
    var n = 999;
    alert(n);//999
}
alert(n);//报错

2.3 链式做用域

  父对象的全部变量,对子对象都是可见的,反之则不成立

//子对象会一级一级地向上寻找全部父对象的变量
function f1() {
    var n = 999;
    function f2() {
        //n对f2可见
        alert(n); // 999
    }
}

 

3. 闭包Closure

   什么是闭包; 定义在一个函数内部的函数 (闭包就是可以读取其余函数内部变量的函数)

//下面的f2就是一个闭包
function f1() {
    var n = 999;
    function f2() {
        alert(n);
    }
    return f2;
}
var result = f1();
result(); // 999
//注意result后跟的(),这对括号才是实际调用

用途:

  • 读取函数内部的变量
  • 让函数内部变量的值始终保持在内存中

闭包执行时的this指针指向问题

var name = "The Window";
var object = {
    name: "My Object",
    getNameFunc: function () {
        return function () {
            return this.name;
        };
    }
};

alert(object.getNameFunc()());//The Window
//上面这句解开后等于 
alert(function () { return this.name; }()); //此时this指针指向当前域下的name="The Window"
var name = "The Window";
var object = {
    name: "My Object",
  getNameFunc: function () {
   var that = this;
      return function () {
          return that.name;
     };
  }
};

alert(object.getNameFunc()());//My Object //分解以下
alert(function () { return that.name; }());//that是对object内部this变量的引用, object内部this指向实例自己
alert(function () { return object.name; }());//最终如此

 

 

refers:

http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_encapsulation.html

http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html