secrets of the javascript Ninja (Function Prototypes)(javascript忍者的秘密)

简介:

       函数原型有很多用途,比如可以用来向一个函数实例上添加一些属性,但是它的一个最主要用途是使JavaScript能够以面向对象的方式编程。

实例化和原型(Instantiation 和 prototypes)

所有函数默认的都会有一个含有空对象的prototype属性,它的这个特性只有在实例化后才会有用,为了能够理解它的这种特性是多么的重要,需要知道一个重要的原则:函数具有双重功能,它可以作为一个平常的函数,也可以作为一个类。

我们可以通过下面一个小例子来看看如何使用prototype属性向一个函数上添加一个功能
  1. function Ninja(){} Ninja.prototype.swingSword=function(){ return true; } var ninja=Ninja(); alert(ninja);//undefined,说明不是Ninja的一个实例 var ninja2=new Ninja(); alert(ninja2.swingSword);//true 
  1. 从上面的这个例子,我们可以发现以下两个问题:

         1.为了产生一个函数的实例对象必须使用new操作符调用该函数。

         2.swingSword变成了Ninja的实例ninja2的一个属性。

 

 

对于函数Ninja来说,由于使用new操作符调用它,我们也可以认为他是一个构造函数。这就意味着,它使用new操作符调用函数的时候,该函数中this所指向的上下文就是对象自身的实例(即和prototype相同),这段话不是太好理解,来让我们看一个例子:

function Ninja(){ this.swung = false; // Should return true this.swingSword = function(){ return !this.swung; }; } // Should return false, but will be overridden Ninja.prototype.swingSword = function(){ return this.swung; }; var ninja = new Ninja(); alert(ninja.swingSword()); 

从上面的例子我们可以发现实例对象调用它的同名方法的顺序

 

1.绑定在prototype上的属性。

2.绑定在构造函数内的属性。

 

 

 

 

另外一个需要了解的是绑定在prototype上的属性,他可以被更新和改变,即使一个对象被实例化后:如下

 

function Ninja(){ this.swung = true; } var ninja = new Ninja(); Ninja.prototype.swingSword = function(){ return this.swung; }; alert(ninja.swingSword()); 

 

 

 

 

 

对象类型

还是以例子说话:

function Ninja(){} var ninja = new Ninja(); alert(typeof ninja); alert(ninja instanceof Ninja); alert(ninja.constructor == Ninja); 

从上面的例子中,我们可以看到:

 

1.所有的示例对象如果使用typeof检测都是object类型

2.instanceof 实例对象是由那个函数生成的。

3.任何实例都有个constructor属性,用来引用生成该实例对象的构造函数

 

 

 

 

为了证明第三个观点,下面来看一个简单的例子:

 

 

var ninja = new Ninja(); var ninja2 = new ninja.constructor(); alert(ninja2 instanceof Ninja);//true 

 

 

 

 

 

 

继承与prototype链

在这里我们还可以看到instanceof的一个重要特性:

 

function Person(){} Person.prototype.dance = function(){}; function Ninja(){} // Achieve similar, but non-inheritable, results Ninja.prototype = Person.prototype; Ninja.prototype = { dance: Person.prototype.dance }; // Only this maintains the prototype chain Ninja.prototype = new Person(); var ninja = new Ninja(); alert(ninja instanceof Ninja);//true alert(ninja instanceof Person);//true alert(ninja instanceof Object);//true 

 

有很多方法从函数的prototype属性上复制功能(方法和函数),但是只有一种情况能够形成prototype链。即:SubFunction.prototype = new SuperFunction();.

 

 

 

 

 

 

HTML prototypes

在Internet Explorer 8, Firefox, Safari, 和 Opera这些浏览器中这些可以使用prototype扩展dom元素: 来看看一个简短的例子:

<div id="a">I'm going to be removed.</div> <div id="b">Me too!</div> HTMLElement.prototype.remove = function(){ if ( this.parentNode ) this.parentNode.removeChild( this ); }; // Old way var a = document.getElementById("a"); a.parentNode.removeChild( a ); // New way document.getElementById("b").remove(); 

目录
相关文章
|
JavaScript 前端开发
JavaScript实现的水果忍者游戏,支持鼠标操作
JavaScript实现的水果忍者游戏,支持鼠标操作
118 0
JavaScript实现的水果忍者游戏,支持鼠标操作
|
JavaScript 前端开发 Java
|
JavaScript 前端开发 测试技术
《JavaScript忍者秘籍》——导读
Web应用程序将为用户提供丰富的用户界面体验,没有JavaScript,我们也就只能显示几张小图片。Web开发人员比以往任何时候都更需要熟练掌握能够为Web应用程序带来生命的语言。
936 0
|
JavaScript 前端开发 测试技术
《JavaScript忍者秘籍》——2.5 总结
我们研究了在代码执行时,如何使用日志记录来观察代码的行为,我们甚至实现了一个方便的方法,可以确保在现代和传统浏览器上都能够成功记录日志,不管它们之间有多少差异。
1337 0
|
前端开发 JavaScript 测试技术
《JavaScript忍者秘籍》——2.4 测试套件基础知识
内部的实现函数runTest(),在测试排队时从列中移除时进行调用。它用于检查当前套件目前是否没被暂停以及队列中是否有测试任务,一旦满足情况,将从队列中取出一个测试并尝试执行它。此外,测试组完成执行之后,runTest()会检查该套件目前是否暂停了,如果没暂停(这意味着,测试组中只有异步测试),runTest()将开始执行下一组测试。
1328 0