- 浏览: 1230952 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
lankk:
lankk 写道事实上,在运行String s1=new St ...
理解String 及 String.intern() 在实际中的应用 -
lankk:
事实上,在运行String s1=new String(&qu ...
理解String 及 String.intern() 在实际中的应用 -
lankk:
同意1楼的说法http://docs.oracle.com/j ...
理解String 及 String.intern() 在实际中的应用 -
raoyutao:
...
jdk 线程池 ThreadPoolExecutor -
hongdanning:
理解了。之前困惑的一些明白了。谢谢分享。
理解String 及 String.intern() 在实际中的应用
笔记
function myfunc () { alert("hello"); }; myfunc(); //这里调用myfunc,输出yeah 而不是hello function myfunc () { alert("yeah"); }; myfunc(); //这里调用myfunc,当然输出yeah
按理说,两个签名完全相同的函数,在其他编程语言中应该是非法的。但在JavaScript 中,这没错。不过,程序运行之后却发现一
个奇怪的现象:两次调用都只是最后那个函数里输出的值!显然第一个函数没有起到任何作用。这又是为什么呢?
5
原来,JavaScript 执行引擎并非一行一行地分析和执行程序,而是一段一段地分析执行的。而且,在同一段程序的分析执行中,定
义式的函数语句会被提取出来优先执行。函数定义执行完之后,才会按顺序执行其他语句代码。也就是说,在第一次调用myfunc 之前,
第一个函数语句定义的代码逻辑,已被第二个函数定义语句覆盖了。所以,两次都调用都是执行最后一个函数逻辑了。
<script> function myfunc () { alert("hello"); }; myfunc(); //这里调用myfunc,输出hello </script> <script> function myfunc () { alert("yeah"); }; myfunc(); //这里调用myfunc,输出yeah </script>
这时,输出才是各自按顺序来的,也证明了JavaScript 的确是一段段地执行的。
一段代码中的定义式函数语句会优先执行,这似乎有点象静态语言的编译概念。所以,这一特征也被有些人称为:JavaScript 的“预
编译”。
function WhoAmI() //定义一个函数WhoAmI { alert("I'm " + this.name + " of " + typeof(this)); }; WhoAmI(); //此时是this 当前这段代码的全局对象,在浏览器中就是window 对象,其name 属性为空字符串。 输出:I'm of object var BillGates = {name: "Bill Gates"}; BillGates.WhoAmI = WhoAmI; //将函数WhoAmI 作为BillGates 的方法。 BillGates.WhoAmI(); //此时的this 是BillGates。输出:I'm Bill Gates of object var SteveJobs = {name: "Steve Jobs"}; SteveJobs.WhoAmI = WhoAmI; //将函数WhoAmI 作为SteveJobs 的方法。 SteveJobs.WhoAmI(); //此时的this 是SteveJobs。输出:I'm Steve Jobs of object WhoAmI.call(BillGates); //直接将BillGates 作为this,调用WhoAmI。输出:I'm Bill Gates of object WhoAmI.call(SteveJobs); //直接将SteveJobs 作为this,调用WhoAmI。输出:I'm Steve Jobs of object 8 BillGates.WhoAmI.call(SteveJobs); //将SteveJobs 作为this,却调用BillGates 的WhoAmI 方法。输出: I'm Steve Jobs of object SteveJobs.WhoAmI.call(BillGates); //将BillGates 作为this,却调用SteveJobs 的WhoAmI 方法。输出: I'm Bill Gates of object WhoAmI.WhoAmI = WhoAmI; //将WhoAmI 函数设置为自身的方法。 WhoAmI.name = "WhoAmI"; WhoAmI.WhoAmI(); //此时的this 是WhoAmI 函数自己。输出:I'm WhoAmI of function ({name: "nobody", WhoAmI: WhoAmI}).
从上面的代码可以看出,同一个函数可以从不同的角度来调用,this 并不一定是函数本身所属的对象。this 只是在任意对象和
function 元素结合时的一个概念,是种结合比起一般对象语言的默认结合更加灵活,显得更加超然和洒脱。
在 JavaScript 函数中,你只能把this 看成当前要服务的“这个”对象。this 是一个特殊的内置参数,根据this 参数,您可以访问到“这
个”对象的属性和方法,但却不能给this 参数赋值。在一般对象语言中,方法体代码中的 this 可以省略的,成员默认都首先是“自己”
的。但JavaScript 却不同,由于不存在“自我”,当访问“这个”对象时,this 不可省略!
除 JSON 外,在JavaScript 中我们可以使用new 操作符结合一个函数的形式来创建对象。例如:
function MyFunc() {}; //定义一个空函数
var anObj = new MyFunc(); //使用new 操作符,借助MyFun 函数,就创建了一个对象
JavaScript 的这种创建对象的方式可真有意思,如何去理解这种写法呢?
其实,可以把上面的代码改写成这种等价形式:
function MyFunc(){};
var anObj = {}; //创建一个对象
MyFunc.call(anObj); //将anObj 对象作为this 指针调用MyFunc 函数
我们就可以这样理解,JavaScript 先用new 操作符创建了一个对象,紧接着就将这个对象作为this 参数调用了后面的函数。其实,
JavaScript 内部就是这么做的,而且任何函数都可以被这样调用!但从 “anObj = new MyFunc()” 这种形式,我们又看到一个熟悉
的身影,C++和C#不就是这样创建对象的吗?原来,条条大路通灵山,殊途同归啊!
:
1 function Person(name) //带参数的构造函数
2 {
3 this.name = name; //将参数值赋给给this 对象的属性
4 this.SayHello = function() {alert("Hello, I'm " + this.name);}; //给this 对象定义一个SayHello 方法。
5 };
6
7 function Employee(name, salary) //子构造函数
8 {
9 Person.call(this, name); //将this 传给父构造函数
10 this.salary = salary; //设置一个this 的salary 属性
11 this.ShowMeTheMoney = function() {alert(this.name+" $" + this.salary);}; //添加ShowMeTheMoney 方法。
10
12 };
13
14 var BillGates = new Person("Bill Gates"); //用Person 构造函数创建BillGates 对象
15 var SteveJobs = new Employee("Steve Jobs", 1234); //用Empolyee 构造函数创建SteveJobs 对象
16
17 BillGates.SayHello(); //显示:I'm Bill Gates
18 SteveJobs.SayHello(); //显示:I'm Steve Jobs
19 SteveJobs.ShowMeTheMoney(); //显示:Steve Jobs $1234
20
21 alert(BillGates.constructor == Person); //显示:true
22 alert(SteveJobs.constructor == Employee); //显示:true
23
24 alert(BillGates.SayHello == SteveJobs.SayHello); //显示:false
这段代码表明,函数不但可以当作构造函数,而且还可以带参数,还可以为对象添加成员和方法。其中的第9 行,Employee 构造
函数又将自己接收的this 作为参数调用Person 构造函数,这就是相当于调用基类的构造函数。第21、22 行还表明这样一个意思:
BillGates 是由Person 构造的,而SteveJobs 是由Employee 构造的。对象内置的constructor 属性还指明了构造对象所用的具体
函数!
其实,如果你愿意把函数当作“类”的话,她就是“类”,因为她本来就有“类”的那些特征。难道不是吗?她生出的儿子各个都有相同的
特征,而且构造函数也与类同名嘛!
但要注意的是,用构造函数操作this 对象创建出来的每一个对象,不但具有各自的成员数据,而且还具有各自的方法数据。换句话
说,方法的代码体(体现函数逻辑的数据)在每一个对象中都存在一个副本。尽管每一个代码副本的逻辑是相同的,但对象们确实是各自
保存了一份代码体。上例中的最后一句说明了这一实事,这也解释了JavaScript 中的函数就是对象的概念。
同一类的对象各自有一份方法代码显然是一种浪费。在传统的对象语言中,方法函数并不象JavaScript 那样是个对象概念。即使也
有象函数指针、方法指针或委托那样的变化形式,但其实质也是对同一份代码的引用。一般的对象语言很难遇到这种情况。
不过,JavaScript 语言有大的灵活性。我们可以先定义一份唯一的方法函数体,并在构造this 对象时使用这唯一的函数对象作为其
方法,就能共享方法逻辑。例如:
function SayHello() //先定义一份SayHello 函数代码
{
alert("Hello, I'm " + this.name);
};
function Person(name) //带参数的构造函数
{
this.name = name; //将参数值赋给给this 对象的属性
this.SayHello = SayHello; //给this 对象SayHello 方法赋值为前面那份SayHello 代码。
};
var BillGates = new Person("Bill Gates"); //创建BillGates 对象
var SteveJobs = new Person("Steve Jobs"); //创建SteveJobs 对象
alert(BillGates.SayHello == SteveJobs.SayHello); //显示:true
11
其中,最后一行的输出结果表明两个对象确实共享了一个函数对象。虽然,这段程序达到了共享了一份方法代码的目的,但却不怎么
优雅。因为,定义SayHello 方法时反映不出其与Person 类的关系。“优雅”这个词用来形容代码,也不知道是谁先提出来的。不过,
这个词反映了程序员已经从追求代码的正确、高效、可靠和易读等基础上,向着追求代码的美观感觉和艺术境界的层次发展,程序人生
又多了些浪漫色彩。
显然,JavaScript 早想到了这一问题,她的设计者们为此提供了一个有趣的prototype 概念。
原型扩展
想必君的悟性极高,可能你会这样想:如果在JavaScript 内置的那些如Object 和Function 等函数的prototype 上添加些新的方
法和属性,是不是就能扩展JavaScript 的功能呢?
那么,恭喜你,你得到了!
在 AJAX 技术迅猛发展的今天,许多成功的AJAX 项目的JavaScript 运行库都大量扩展了内置函数的prototype 功能。比如微软的
ASP.NET AJAX,就给这些内置函数及其prototype 添加了大量的新特性,从而增强了JavaScript 的功能。
我们来看一段摘自MicrosoftAjax.debug.js 中的代码:
String.prototype.trim = function String$trim() {
if (arguments.length !== 0) throw Error.parameterCount();
return this.replace(/^\s+|\s+$/g, '');
}
这段代码就是给内置String 函数的prototype 扩展了一个trim 方法,于是所有的String 类对象都有了trim 方法了。有了这个扩
展,今后要去除字符串两段的空白,就不用再分别处理了,因为任何字符串都有了这个扩展功能,只要调用即可,真的很方便。
当然,几乎很少有人去给Object 的prototype 添加方法,因为那会影响到所有的对象,除非在你的架构中这种方法的确是所有对
象都需要的。
function Person(firstName, lastName, age)
{
//私有变量:
var _firstName = firstName;
var _lastName = lastName;
//公共变量:
this.age = age;
//方法:
15
this.getName = function()
{
return(firstName + " " + lastName);
};
this.SayHello = function()
{
alert("Hello, I'm " + firstName + " " + lastName);
};
};
var BillGates = new Person("Bill", "Gates", 53);
var SteveJobs = new Person("Steve", "Jobs", 53);
BillGates.SayHello();
SteveJobs.SayHello();
alert(BillGates.getName() + " " + BillGates.age);
alert(BillGates.firstName); //这里不能访问到私有变量
很显然,这种模型的类描述特别象C#语言的描述形式,在一个构造函数里依次定义了私有成员、公共属性和可用的方法,显得非常
优雅嘛。特别是“闭包”机制可以模拟对私有成员的保护机制,做得非常漂亮。
所谓的“闭包”,就是在构造函数体内定义另外的函数作为目标对象的方法函数,而这个对象的方法函数反过来引用外层外层函数体中
的临时变量。这使得只要目标对象在生存期内始终能保持其方法,就能间接保持原构造函数体当时用到的临时变量值。尽管最开始的构
造函数调用已经结束,临时变量的名称也都消失了,但在目标对象的方法内却始终能引用到该变量的值,而且该值只能通这种方法来访
问。即使再次调用相同的构造函数,但只会生成新对象和方法,新的临时变量只是对应新的值,和上次那次调用的是各自独立的。的确
很巧妙!
但是前面我们说过,给每一个对象设置一份方法是一种很大的浪费。还有,“闭包”这种间接保持变量值的机制,往往会给JavaSript
的垃圾回收器制造难题。特别是遇到对象间复杂的循环引用时,垃圾回收的判断逻辑非常复杂。无独有偶,IE 浏览器早期版本确实存在
JavaSript 垃圾回收方面的内存泄漏问题。再加上“闭包”模型在性能测试方面的表现不佳,微软最终放弃了“闭包”模型,而改用“原型”
模型。正所谓“有得必有失”嘛。
end
发表评论
-
node npm windows
2018-10-15 16:06 1239在window下npm install, 遇到一 ... -
How to use requirejs in client side
2016-12-05 16:27 468How to use requirejs in client ... -
dojo get post demo
2015-07-31 14:37 1051dojo.xhrGet({ u ... -
dgrid之Grid Pagination 集成分页 后台rest service
2015-05-19 13:09 2378dgrid之Grid集成分页 后台rest serv ... -
angular 1.3.15 表达式bug
2015-04-15 13:41 871不确定这是 angular的还是浏览器的, chrom ... -
书上看来的js闭包列子
2014-01-22 12:19 1511js闭包列子 <html> <h ... -
犀牛书 & JavaScript Web Applications notes
2012-10-20 22:10 1650https://www.evernote.com/shar ... -
犀牛书 笔记
2012-10-15 09:51 5http://www.evernote.com/shard/s ... -
点击其他地方隐藏popup窗口
2011-12-14 16:54 2268现在系统有一个弹出的日期选择窗口, 要求在窗口弹出后, 点击窗 ... -
jqgrid 隔行变底色
2011-10-20 19:07 5266jgrid默认配置没有 隔行变底色的选项 查看源码 看他怎 ... -
twitter search jquery plugin
2011-06-20 16:05 1981详见 http://tweet.seaofclouds.co ... -
js encodeURIComponent encodeURI decodeURI
2011-05-26 15:48 1480js encodeURIComponent enco ... -
jquery hover hasClass insertBefore live blockUI children notice
2011-05-17 18:22 1866hover $(".onenote& ... -
jquery validate
2011-05-05 18:44 1184function(){ $("#re ... -
js 测试 用户名 中文 英文 数字 判断 函数 是否 存在
2010-11-03 20:24 1786/^((\w)|([\u4E00-\u9FA5])){1,20 ... -
css 滤镜 路径
2010-09-13 20:10 1205在ie6处理png透明的代码是: 1. filt ... -
jquery取得text,areatext,radio,checkbox,select的值
2010-07-09 18:21 1495jquery取得 text,areatext,radio,c ... -
js 遍历对象属性
2010-07-05 12:14 1405<!DOCTYPE html PUBLIC " ... -
jQuery 对Select的操作
2010-06-30 20:36 1117语法解释: 1. $("# ... -
国家地区 js 数组
2010-06-30 19:06 4745en var geolocation= [ [" ...
相关推荐
"悟透JavaScript"这个压缩包文件显然是一份旨在帮助学习者深入理解这门语言的教程资料。从标签"书籍教程-网页制作"我们可以推测,这份教程可能包含了JavaScript在网页制作中的实际应用和相关理论知识。 "悟透...
资源名称:悟透Javascript内容简介:翻开此书的你,也许是Javascript的崇拜者,正想摩拳擦掌地想尝试下学一学这一精巧的语言;也许是80后,90后的程序员或者前端架构师,正被Javascript魔幻般的...
### 悟透JavaScript核心知识点解析 #### 一、编程世界的本质:数据与代码 **悟透JavaScript**这本书深入探讨了编程世界的核心——数据与代码之间的关系。在编程的世界里,一切皆可归结为这两种基本元素:数据与...
悟透JavaScript.mht,悟透JavaScript.mht,悟透JavaScript.mht,悟透JavaScript.mht,悟透JavaScript.mht
由于提供的内容中没有实际的文本信息,只是一些重复的网址链接,所以无法从中生成有关JavaScript的具体知识点。但我可以向你介绍一些JavaScript的基础知识点以及一些高级概念,希望对你的学习有所帮助。 JavaScript...
悟透JAVASCRIPT 美绘本 有图 易学
### JavaScript核心知识点解析 #### 一、编程世界的本质:数据与代码 在编程的世界中,所有事物都可以归纳为两种基本元素:**数据**与**代码**。这两种元素之间的相互作用构成了程序的基础。 - **数据**: 数据是...
在《悟透JavaScript》中,作者深入浅出地解释了JavaScript的基本元素:数据和代码,以及它们之间的关系。JavaScript中的数据类型分为简单数据类型和复杂数据类型,而代码则主要表现为函数形式。 简单数据类型包括...
《悟透JavaScript》是李战撰写的一本JavaScript教程,它以其独特的讲解方式和生动的语言吸引了众多读者。这本书旨在帮助读者深入理解JavaScript这门强大的编程语言,不仅覆盖了基础概念,还涉及了高级特性,使读者...
### 悟透JavaScript #### 数据与代码:编程世界的两大基石 在编程的世界里,所有的一切都可以归结为两种最基本的元素——数据与代码。这两者交织在一起,共同构成了丰富多彩、充满活力的数字世界。 1. **数据**:...
"悟透JavaScript2015"的主题旨在帮助开发者深入理解2015年时JavaScript的核心概念、语法特性以及应用场景。 在2015年,ECMAScript 6(ES6)或称ES2015正式发布,这是JavaScript历史上的一个里程碑。它引入了一系列...
悟透JavaScript.pdf 高清下载
根据提供的文件信息,我们可以归纳出以下几个JavaScript相关的知识点: ### JavaScript基础用法 #### 内联JavaScript 内联JavaScript指的是在HTML元素中直接嵌入JavaScript代码的方式。这种方式常见于`<a>`、`...