全文摘抄自:http://www.cnblogs.com/xdp-gacl/
1. JavaScript中的null、Nan、undefined的区别是什么?
js中的数据类型有undefined,boolean,number,string,object等5种,前4种为原始类型,第5种为引用类型。
var tmp = undefined;
if (typeof(tmp) == "undefined"){
alert("undefined");
}
var tmp = null;
if (!tmp && typeof(tmp)!="undefined" && tmp!=0){
alert("null");
}
var tmp = 0/0;
if(isNaN(tmp)){
alert("NaN");
}
var tmp = undefined;
if (tmp== undefined)
{
alert("null or undefined");
}
if (tmp== null)
{
alert("null or undefined");
}
var tmp = null;
if (!tmp)
{
alert("null or undefined or NaN");
}
2. 逻辑运算NOT、AND
逻辑 NOT一定返回Boolen值,NOT 运算符的行为如下:
- 如果运算数是对象,返回 false
- 如果运算数是数字 0,返回 true
- 如果运算数是 0 以外的任何数字,返回 false
- 如果运算数是 null,返回 true
- 如果运算数是 NaN,返回 true
- 如果运算数是 undefined,发生错误
逻辑AND运算并不一定返回Boolean值,AND运算符的运算行为如下:
- 如果一个运算数是对象,另一个是 Boolean 值true,返回该对象,false和对象返回false。
- 如果两个运算数都是对象,返回第二个对象。
- 如果某个运算数是 null,返回 null。
- 如果某个运算数是 NaN,返回 NaN。
- 如果某个运算数是 undefined,发生错误。
- 如果两个运算数都是boolean类型,则返回boolean值
- false&&null 返回false
- false&&NaN返回false
- NaN&&null 返回NaN
- null&&NaN 返回null
与Java中的逻辑AND运算相似,JavaScript 中的逻辑AND运算也是简便运算,即如果第一个运算数决定了结果,就不再计算第二个运算数。对于逻辑AND运算来说,如果第一个运算数是false,那么无论第二个运算数的值是什么,结果都不可能等于true。
3.JavaScript数据类型判断
Number类型判断:
function isNumber(val){
return typeof val === 'number' && isFinite(val);
}
isFinite() 函数用于检查其参数是否是无穷大,如果 number 是有限数字(或可转换为有限数字),那么返回 true。否则,如果 number 是 NaN(非数字),或者是正、负无穷大的数,则返回 false。
boolen数据类型判断:
function isBooleanType(val) {
return typeof val ==="boolean";
}
string数据类型判断:
function isStringType(val) {
return typeof val === "string";
}
undefined数据类型判断:
function isUndefined(val) {
return typeof val === "undefined";
}
Object数据类型判断:
function isObj(str){
if(str === null || typeof str === 'undefined'){
return false;
}
return typeof str === 'object';
}
由于当变量是空值Null时,typeof也会返回object,所以Object不能直接用 typeof 判断。
Null数据类型判断:
function isNull(val){
return val === null;
}
Array数据类型判断:
数组类型不可用typeof来判断。因为当变量是数组类型是,typeof会返回object。这里有两种方法判断数组类型:
/*判断变量arr是不是数组
方法一
*/
function isArray1(arr) {
return Object.prototype.toString.apply(arr) === '[object Array]';
}
/*判断变量arr是不是数组
方法二
*/
function isArray2(arr) {
if(arr === null || typeof arr === 'undefined'){
return false;
}
return arr.constructor === Array;
}
4. JavaScript函数可变参数的实现
JavaScript的函数天然支持可变参数,JavaScript有一个arguments变量可以访问所有传到函数内部的参数。
<script type="text/javascript">
/*add函数是一个参数可变的函数*/
function add(){
var result=0;
for(var i=0;i<arguments.length;i++){
//alert(arguments[i]);
result+=arguments[i];
}
return result;
}
alert("add(1,2,3)="+add(1,2,3));//调用add函数时传入3个参数
alert("add(1,2,3,4,5,6)="+add(1,2,3,4,5,6));//调用add函数时传入6个参数
alert("add()="+add());//调用add函数时不传入参数
alert("add(1,\"HelloWorld\")="+add(1,"HelloWorld"));//调用add函数时传入不同类型的参数
</script>
5. javascript创建动态函数
JavaScript支持创建动态函数,动态函数必须用Function对象来定义(Function是javascript中的一个对象,是固定不变的,规定Function对象的"F"必须大写,当是function的时候,我们知道是定义函数的时候所使用的一个关键字:function funName(x,y),当是Function的时候(F大写的时候),我们知道是javascript中的对象)
创建动态函数的基本格式:var 变量名 = new Function("参数1","参数2","参数n","执行语句");
使用new关键字(new是javascript中一个关键字,也是固定的,我们在定义动态函数的时候必须要使用new来创建这个Function对象)我们先定义一个变量: var 变量名,在这里,变量名是随便的,然后我们再使用new关键字创建一个Function对象,然后再把这个对象赋值给这个任意的变量,也就是:var 变量名 = new Function("参数1","参数2","参数n","执行语句");Function后面的括号里先是传递给函数的参数,然后用一个逗号(,)隔开然后是这个函数要执行的功能的代码
<script type="text/javascript">
var square = new Function ("x","y","var sum ; sum = x+y;return sum;");
alert("square(2,3)的结果是:"+square(2,3));
</script>
square是动态创建的函数,在Function对象后面的括号里的每一部分内容都必须是字符串形式的,也就是说都必须用引号(""或者是'')括起来,第一部分是传递给这个动态函数的第一个参数“x”,第二部分是传递给这个动态函数的第二个参数“y“,第三部分是这个函数要完成的功能的代码,这个函数要完成的功能是定义一个变量sum,让sum等于传递给这个函数的两个参数x和y的和,然后返回他们相加以后的值(return sum)。
alert(function(i1, i2) { return i1 + i2; }(10,10));
6. JavaScript中的数组
<script type="text/javascript">
var names = new Array();//普通方式声明数组,不需要指明数组的长度
names[0] = "孤傲苍狼";
names[1] = "白虎神皇";
names[2] = "灭世魔尊";
for (var i = 0; i < names.length; i++) {
document.write("names["+i+"] = "+names[i]);
document.write("<br/>");
}
var pinyins = new Array();
pinyins["人"] = "ren";
pinyins["口"] = "kou";
pinyins["手"] = "shou";
document.write("pinyins[\"人\"] = "+pinyins["人"]);
document.write("<br/>");
document.write("pinyins.手 = "+pinyins.手);//像Hashtable、Dictionary那样用,而且像它们一样效率高。
document.write("<br/>");
//Array的简化声明
var arr1 = [3, 5];//普通数组初始化
for (var i = 0; i < arr1.length; i++) {
document.write("arr1["+i+"] = "+arr1[i]);
document.write("<br/>");
}
</script>
7. Javascript面向(基于)对象编程
<script type="text/javascript">
/*定义一个Person类*/
function Person(_name,_age,_salary){
//Person类的公开属性,类的公开属性的定义方式是:”this.属性名“
this.Name=_name;
//Person类的私有属性,类的私有属性的定义方式是:”var 属性名“
var Age=_age;
var Salary=_salary;
//定义Person类的公开方法(特权方法),类的公开方法的定义方式是:”this.functionName=function(){.....}“
this.Show=function(){
alert("Age="+Age+"\t"+"Salary="+Salary);//在公开方法里面访问类的私有属性是允许的
}
/*
定义Person类的私有方法(内部方法),
类的私有方法的定义方式是:”function functionName(){.....}“,
或者 var functionName=function(){....}
*/
function privateFn(){
alert("我是Person类的私有函数privateFn");
}
var privateFn2=function(){
alert("我是Person类的私有函数privateFn2");
}
}
/*通过prototype给可以类的所有对象添加公共(public)方法,
但是这种方式定义的方法不能去访问类的私有属性和私有方法*/
Person.prototype.Fn=function(){
alert("访问公共属性this.Name="+this.Name);//访问公共属性,OK的
//alert("访问私有属性Aag="+Age);//访问私有属性,这里会报错“Age未定义”
//privateFn();//调用私有方法,这里会报错“缺少对象”
}
var p1 = new Person("孤傲苍狼",24,2300);
alert("p1.Name="+p1.Name);//访问公有属性,这是可以正常访问的
alert("p1.Age="+p1.Age+"\t"+"p1.Salary="+p1.Salary);//不能使用类的对象去直接访问类私有属性,这是访问不了的,结果都是undefined
p1.Show();//调用类的公共函数,这次允许的
p1.Fn();//调用类的公共函数,这次允许的
//alert("p1.privateFn():"+p1.privateFn()+" p1.privateFn2():"+p1.privateFn2());//不能使用类的对象去调用类的私有方法,这里会报错”对象不支持此属性或者方法“
</script>
继承的范例如下:
<script type="text/javascript">
/*定义Stu类*/
function Stu(name,age){
this.Name=name;
this.Age=age;
this.Show=function(){
window.alert("我的名字是:"+this.Name+",今年:"+this.Age);
}
this.SayHello = function(){
window.alert("Hello,"+this.Name);
}
}
/*定义MidStu类*/
function MidStu(name,age){
this.stu=Stu;//MidStu类继承Stu类
this.stu(name,age);//JS中实际上是通过对象冒充来实现继承的,这句话不能少,因为JS是动态语言,如果不执行,则不能实现继承效果
/*
从父类继承下来的公共方法,可以根据实际情况选择重写
*/
//在子类MidStu中重写父类Stu的Show方法
/*this.Show=function(){
alert("MidStu.Show()");
}*/
//在子类MidStu中重写父类Stu的SayHello方法
this.SayHello=function(){
alert("你好,"+this.Name);
}
}
var midStu = new MidStu("孤傲苍狼",24);//创建一个MidStu类实例对象
alert("访问继承下来的属性Name和Age,midStu.Name="+midStu.Name+",midStu.Name="+midStu.Age);//访问继承下来的属性
midStu.Show();//调用从父类Stu继承下来的Show方法
midStu.SayHello();//调用从父类Stu继承下来的SayHello方法,SayHello()在子类中进行了重写,这里调用的是重写过后的SayHello()方法
</script>
8. JavaScript的Object类
function extend(target,source){//target 旧的 source新的
for (var i in source){
if(target.hasOwnProperty(i)){
target[i]=source[i];
}
}
return target;
}
var a1={"first":1,"second":"lyl","third":"bob"};
var b1={"third":"leo"};
extend(a1,b1);
for(var i in a1){
alert(a1[i]);//原本是bob,现在变成leo了
}
<script type="text/javascript">
function foo(){
this.name = 'foo';
}
function bar(){
}
bar.prototype = new foo();
var goo = new bar();
alert(goo.name); //foo
alert(bar.prototype.isPrototypeOf(goo));//true,在bar的原型链中有当前对象goo,则isPrototypeOf方法返回true
</script>
var Car = function(){};
Car.prototype.hello = function(){
alert("hello car");
};
var car = new Car();
car.f = function() {
alert("自定义方法");
}
document.write("<pre>");
document.writeln("car.hasOwnProperty(\"f\")的结果是:"+car.hasOwnProperty("f"));//ture,car对象有f方法
document.writeln("car.propertyIsEnumerable(\"f\")的结果是:"+car.propertyIsEnumerable("f"));//ture,car对象有f方法,f方法是可以被枚举的
document.writeln("car.hasOwnProperty(\"hello\")"+car.hasOwnProperty("hello")); // false,因为car本身没有hello方法
document.writeln("car.propertyIsEnumerable(\"hello\")的结果是:"+car.propertyIsEnumerable("hello")); // false,没有这个方法当然不能枚举
document.writeln("car.constructor.prototype.hasOwnProperty(\"hello\")的结果是:"+car.constructor.prototype.hasOwnProperty("hello"));// true,car的类Car的原型有hello方法
document.writeln("car.constructor.prototype.propertyIsEnumerable(\"hello\")的结果是:"+car.constructor.prototype.propertyIsEnumerable("hello"));// true, car的类的Car的原型hello方法是可以被枚举的
document.writeln("Car.prototype.hasOwnProperty(\"hello\")的结果是:"+Car.prototype.hasOwnProperty("hello"));// true,car的类Car的原型有hello方法
document.writeln("Car.prototype.propertyIsEnumerable(\"hello\")的结果是:"+Car.prototype.propertyIsEnumerable("hello"));
document.write("</pre>");
9.JavaScript Object的三种创建方式
/*定义一个Person类*/
function Person(_name,_age,_salary){
//Person类的公开属性,类的公开属性的定义方式是:”this.属性名“
this.name=_name;
//Person类的私有属性,类的私有属性的定义方式是:”var 属性名“
var age=_age;//私有属性
var salary=_salary;//私有属性
/*定义私有属性Age的对外公开访问方法*/
this.setAge = function(intAge) {
age = intAge;
}
/*定义私有属性Age的对外公开访问方法*/
this.getAge = function() {
return age;
}
//定义Person类的公开方法(特权方法),类的公开方法的定义方式是:”this.functionName=function(){.....}“
this.Show=function(){
document.writeln("在公开方法里面访问类的私有属性是允许的,age="+age+"\t"+"salary="+salary);//在公开方法里面访问类的私有属性是允许的
}
//公共方法
this.publicMethod = function(){
document.writeln("在公开方法里面访问类的私有方法是允许的");
privateFn();//在公开方法里面调用类的私有方法
privateFn2();//在公开方法里面调用类的私有方法
}
/*
定义Person类的私有方法(内部方法),
类的私有方法的定义方式是:”function functionName(){.....}“,
或者 var functionName=function(){....}
*/
function privateFn(){
document.writeln("我是Person类的私有函数privateFn");
}
var privateFn2=function(){
document.writeln("我是Person类的私有函数privateFn2");
}
}
这种方式的优点是:可以根据参数来构造不同的对象实例 ,每个对象的属性一般是不相同的,缺点是构造每个实例对象时, 方法不能共享,Person类里面定义的那些方法,p1对象有一份,p2也有一份,那么在内存中就得开辟两块内存空间来分别存储p1的方法和p2的方法,这样就造成了内存的浪费。对于一个类的不同实例对象,这些对象的属性一般是不相同的,但是方法是相同的,所以节约内存的做法就是把方法放到内存的一块区域中存放,然后每个实例对象都从这块内存中取出方法。
/*定义类Person2*/
function Person2(){
}
/*使用原型方式给类定义public属性和public方法更加优雅的写法*/
Person2.prototype = {
name:"",//public属性
age:0,//public属性
weight:0,//public属性
height:0,//public属性
/*public方法*/
init:function(_name,_age,_weight,_height) {
this.name = _name;
this.age = _age;
this.weight=_weight;
this.height=_height;
document.writeln("this.name="+this.name+",this.age="+this.age+",this.weight="+this.weight+",this.height="+this.height);
},
/*public方法*/
show:function(){
document.writeln("show method");
}
};
测试代码如下:
document.write("<pre>");
var p2_1 = new Person2();
var p2_2 = new Person2();
p2_1.init("孤傲苍狼",24,115,160);
p2_2.init("白虎神皇",25,120,170);
document.writeln("p2_1.name="+p2_1.name+",p2_1.age="+p2_1.age+",p2_1.weight="+p2_1.weight+",p2_1.height="+p2_1.height);//访问公有属性,这是可以正常访问的
document.writeln("p2_2.name="+p2_2.name+",p2_2.age="+p2_2.age+",p2_2.weight="+p2_2.weight+",p2_2.height="+p2_2.height);//访问公有属性,这是可以正常访问的
document.writeln("p2_1 instanceof Person2的结果是:"+(p2_1 instanceof Person2));//p2_1是Person2类的实例,结果是true
document.writeln("p2_2 instanceof Person2的结果是:"+(p2_2 instanceof Person2));//p2_2是Person2类的实例,结果是true
//当==两边的内容是对象或者是对象的函数属性时,则比较内存地址是否相等
document.writeln("当==两边的内容是对象或者是对象的函数属性时,则比较内存地址是否相等");
document.writeln("比较p2_1和p2_2这两个对象的init方法的内存地址是否一样:p2_1.init == p2_2.init的结果是:"+(p2_1.init == p2_2.init));//true
p2_1.name="灭世魔尊";//为公共属性重新赋值
document.writeln("p2_1.name="+p2_1.name);//访问公有属性,这是可以正常访问的
p2_1.show();//调用类的公共函数,这次允许的
document.write("</pre>");
原型方式的优点:所有对象实例都共享类中定义的方法,这样就没有造成内存浪费。缺点,第一,不能定义类的私有属性和私有方法,第二,给在创建对象,给对象的属性初始化时,需要
额外写一个初始化对象的方法。
/*定义一个Person类*/
function Person(_name,_age,_salary){
//在Person类内部定义类的public属性和private属性以及private方法
//Person类的公开属性,类的公开属性的定义方式是:”this.属性名“
this.name=_name;
//Person类的私有属性,类的私有属性的定义方式是:”var 属性名“
var age=_age;//私有属性,只能在类内部使用
var salary=_salary;//私有属性,只能在类内部使用
/*
定义Person类的私有方法(内部方法),只能在类内部使用
类的私有方法的定义方式是:”function functionName(){.....}“,
或者 var functionName=function(){....}
*/
function privateFn(){
document.write("<pre>");
document.writeln("我是Person类的私有属性age,只能在Person类内部使用,初始化后age="+age);
document.writeln("我是Person类的私有函数privateFn,只能在Person类内部使用");
document.write("</pre>");
}
var privateFn2=function(){
document.write("<pre>");
document.writeln("我是Person类的私有属性salary,只能在Person类内部使用,初始化后salary="+salary);
document.writeln("我是Person类的私有函数privateFn2,只能在Person类内部使用");
document.write("</pre>");
}
privateFn();//在Person类内部调用私有方法
privateFn2();//在Person类内部调用私有方法
}
//使用prototype原型方式定义的方法(public方法)是无法访问类的私有属性和私有方法的
//使用prototype原型方式定义Person类的方public方法
Person.prototype={
setName:function(_name){
this.name = _name;
//privateFn();//不能调用Person类定义的私有方法privateFn(),会报错:缺少对象
},
getName:function(){
return this.name;
},
show:function(){
document.writeln("公开方法show");
},
//公共方法
publicMethod:function(){
document.writeln("公开方法publicMethod");
}
};
第三种方式通过前两种方式的结合,算是达到了一个比较理想的写法了,可以通过传参构造对象实例,对象实例都共享同一份方法不造成内存浪费。第三种方式在开发中用得最多。
10. JavaScript的闭包(Cloure)概念
var n=999;//定义全局变量n
function f1(){
alert("在函数内部访问全局变量n,n="+n);//在函数内部访问全局变量n
}
f1(); // 999
function f1(){
var n=999;//在f1函数内部定义局部变量n
}
alert("在函数外部访问局部变量n,n="+n); //在函数外部访问局部变量n,错误:n未定义
这里有一个地方需要注意,函数内部声明变量的时候,一定要使用
var命令。如果不用的话,实际上是声明了一个全局变量!
function f1(){
n=999;
}
f1();
alert("n在f1函数内部没有使用var来声明,此时n就是一个全局变量,\r\n证明:n="+n+",window.n==n的结果是:"+(window.n==n));
2. 如何从外部读取局部变量
出于种种原因,我们有时候需要得到函数内的局部变量。但是,前面已经说过了,正常情况下,这是办不到的,只有通过变通方法才能实现。那就是在函数的内部,再定义一个函数。
function f1(){
var n=999;//局部变量n
//在f1函数内部声明的f2函数
function f2(){
alert(n);
}
return f2;//将f2函数作为f1函数的返回值
}
var result=f1();//f1调用完后的返回值是一个f2函数,此时result就是f2函数
result(); // 999,调用f2函数
3. 闭包的概念
上一节代码中的f2函数,就是闭包。各种专业文献上的"闭包"(closure)定义非常抽象,比如有这样的一个闭包定义:" JavaScript闭包就是在另一个作用域中保存了一份它从上一级函数或者作用域得到的变量,而这些变量是不会随上一级函数的执行完成而销毁 ",对于这样的闭包定义,我是很难看懂。 我的理解是, 闭包就是能够读取其他函数内部变量的函数 。 由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数" 。所以, 在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁 。
function f1(){
var n=999;
//nAdd是一个没有使用var声明的全局变量,这个变量现在指向了在f1函数内部声明的一个匿名函数
nAdd=function(){n+=1}
function f2(){
alert(n);
}
return f2;
}
var result=f1();//result就是f2函数
result();//第一次调用result函数 999
nAdd();//nAdd代表的就是在f1函数内部声明的一个匿名函数,nAdd()就是在调用匿名函数
result();//第二次调用result函数 1000
11.JavaScript添加动态和静态方法
类名.prototype.方法名 = function([param1],[param2],....[paramn]) {
.................
}
[param1],[param2],....[paramn]这些参数都是可选的
使用这种方式给类添加的扩展方法都是动态的,动态方法是针对类的实例对象的,所以调用必须要用"对象.方法名"的形式去调用,不能用"类名.方法名"的形式去调用!
/*扩展为String类,为String类增加quote(两边加字符)方法*/
String.prototype.quote = function(quotestr) {
if (!quotestr) {
quotestr = "\"";
}
return quotestr + this + quotestr;
};
alert("abc".quote());
alert("abc".quote("|"));
类名.方法名 = function([param1],[param2],....[paramn]) {
.................
}
[param1],[param2],....[paramn]这些参数都是可选的
使用这种方式给类添加的扩展方法都是静态的,动态方法是针对类的实例对象的,所以调用必须要用"对象.方法名"的形式去调用,而静态方法是针对类的,用"类名.方法名"的形式去调用!
// ----------------------------------------------------------------------
// <summary>
// 扩展String类,添加Format静态方法,模仿C#中的String.Format方法
// </summary>
// <returns>str</returns>
// ----------------------------------------------------------------------
if (!String.Format) {
String.Format = function () {
if (arguments.length == 0) {
return null;
}
var str = arguments[0];
if (arguments[1] instanceof Array) {
var arr = arguments[1];
for (var i = 0; i < arr.length; i++) {
var re = new RegExp('\\{' + i + '\\}', 'gm');
str = str.replace(re, arr[i]);
}
} else {
for (var i = 1; i < arguments.length; i++) {
var re = new RegExp('\\{' + (i - 1) + '\\}', 'gm');
str = str.replace(re, arguments[i]);
}
}
return str;
}
}
var str="我是{0},我在总结{1}和{2}的学习,我很喜欢{3}这2门语言!";
//使用"类名.方法名"的形式去调用类的静态方法
str = String.Format(str,"孤傲苍狼","java","JavaScript","'java'和'JavaScript'");//把str中的占位符{0},{1},{2},{3}用具体的内容替换掉
alert(str);
12. 变量提升和函数提升
console.log(a);
var a = 1;
上面代码首先使用console.log方法,在控制台(console)显示变量a的值。这时变量a还没有声明和赋值,所以这是一种错误的做法,但是实际上不会报错。因为存在变量提升,真正运行的是下面的代码。
var a;
console.log(a);
a = 1;
console.log(b);
b = 1;
f();
function f() {}
表面上,上面代码好像在声明之前就调用了函数f。但是实际上,由于“变量提升”,函数f被提升到了代码头部,也就是在调用之前已经声明了。但是,如果采用赋值语句定义函数,JavaScript就会报错。
f();
var f = function (){};
// TypeError: undefined is not a function
13 区块和作用域
{
var a = 1;
}
a // 1
上面代码在区块内部,声明并赋值了变量a,然后在区块外部,变量a依然有效,这说明区块不构成单独的作用域,与不使用区块的情况没有任何区别。所以,单独使用的区块在JavaScript中意义不大,很少出现。区块往往用来构成其他更复杂的语法结构,比如for、if、while、function等。
14. eval命令
eval('var a = 1;');
a // 1
eval没有自己的作用域,都在当前作用域内执行,因此可能会修改当前作用域的变量的值,造成安全问题。
var a = 1;
eval('a = 2');
a // 2
(function f() {
'use strict';
eval('var foo = 123');
console.log(foo); // ReferenceError: foo is not defined
})()
(function f() {
'use strict';
var foo = 1;
eval('foo = 2');
console.log(foo); // 2
})()
15. JavaScript原型链
/*扩展Object类,添加Clone,JS实现克隆的方法*/
Object.prototype.Clone = function(){
var objClone;
if (this.constructor == Object){
objClone = new this.constructor();
}else{
objClone = new this.constructor(this.valueOf());
}
for(var key in this){
if ( objClone[key] != this[key] ){
if ( typeof(this[key]) == 'object' ){
objClone[key] = this[key].Clone();
}else{
objClone[key] = this[key];
}
}
}
objClone.toString = this.toString;
objClone.valueOf = this.valueOf;
return objClone;
}
/*扩展Object类,添加Extend方法来实现JS继承, 目标对象将拥有源对象的所有属性和方法*/
Object.prototype.Extend = function (objDestination, objSource) {
for (var key in objSource) {
if (objSource.hasOwnProperty(key) && objDestination[key] === undefined) {
objDestination[key] = objSource[key];
}
}
return objDestination;
}
16. new运算符是如何工作的