JavaScript高级特征之面向对象笔记
Javascript面向对象
函数
* Arguments对象: * Arguments对象是数组对象 * Arguments对象的length属性可以获取参数的个数 * 利用Arguments对象模拟函数的重载效果(javascript中不存在函数重载)
变量的作用域
* 全局变量与局部变量 * 全局变量:全局域与函数域(局部域) * 局部变量:当前函数域
* 全局域与函数域
* 定义局部变量时,不使用"var",局部变量变成全局变量
* 定义全局变量与局部变量同名时,函数域中只能访问局部变量
匿名函数
没有名的函数
javascript可以将函数作为数据使用。作为函数本体,它像普通的数据一样,不一定要有名字。默认名字的函数被称之为“匿名函数”。例如: function (a){return a;} 匿名函数的两种用法: 可以将匿名函数作为参数传递给其他函数。这样,接收方函数就能利用所传递的函数来完成某些事情。 可以定义某个匿名函数来执行某些一次性任务
回调函数
把一个函数作为参数传递给另一个函数,而作为参数的函数叫做回调函数
1 function add(a, b){ 2 return a() + b(); 3 } 4 var one = function(){return 1;} 5 var two = function(){return 2;} 6 alert(add(one,two)); //output 3 7 8 //可以直接使用匿名函数来替代one()和two(),以作为目标函数的参数 9 alert(add(function(){return 1;}, function(){return 2;})); 10 在这个例子中,函数one和two都是回调函数。 11 当将函数A传递给函数B,并由B来执行A时,A就成了一个回调函数(callback function)。如果A还是一个无名函数,就称之为匿名回调函数。 12 回调函数的优点: 13 它可以在不做命名的情况下传递函数(这意味着可以节省全局变量)。 14 可以将一个函数调用操作委托给另一个函数(这意味着可以节省一些代码编写工作)。 15 回调函数也有助于提升性能。(重要) 16 下面的代码,利用回调函数如何优化? 17 //该函数通过一个循环将其所接收的三个参数分别乘以2,并以数组的形式返回结果 18 function two(a, b, c){ 19 var i, arr = []; 20 for(i = 0;i < 3; i++){ 21 arr[i] = arguments[i] * 2; 22 } 23 return arr; 24 } 25 26 //将接收的参数加一后返回 27 function addone(a){ 28 return a + 1; 29 } 30 31 //测试上面的两个函数 32 alert(two(1, 2, 3)); //output [2, 4, 6] 33 alert(addone(100)); //output 101 34 35 //将三个数据在两个函数之间传递 36 var myarr = []; 37 myarr = two(10, 20, 30); 38 for(var i = 0; i < 3; i++){ 39 myarr[i] = addone(myarr[i]); 40 } 41 alert(myarr); //output [21, 41, 61] 42 /* 43 * 以上代码可以工作,但是显然不够优化。 44 * 这里使用了两次循环。如果处理的数据量很大火循环操作很复杂的话,开销一定不小。 45 */ 46 47 //优化之后的代码(修改two函数) 48 function two(a, b, c, callback){ 49 var i, arr = []; 50 for(i = 0;i < 3; i++){ 51 arr[i] = callback(arguments[i] * 2); 52 } 53 return arr; 54 } 55 56 myarr = two(1, 2, 3, addone); 57 alert(myarr); //output [3, 5, 7] 58 59 //还可以使用匿名函数来替代addone函数 60 myarr = two(1, 2, 3, function addone(a){return a + 1;});
自调函数
定义即调用
第一个小括号:封装函数
第二个小括号:调用函数(传参)
1 自调函数 2 自调函数 —— 其实就是在定义函数后自行调用。例如: 3 ( 4 function(){ 5 alert("javascript"); 6 } 7 )() 8 第一对括号,放置的是一个匿名函数。 9 第二对括号的作用,是“立即调用”。 10 自调函数只需:将匿名函数的定义放进一对括号中,然后外面再跟一对括号即可。 11 12 function(name){ 13 alert("Hello " + name + "!"); 14 } 15 )("javascript") 16 //output Hello javascript! 17 第一个括号中的匿名函数接受一个参数。 18 第二个括号,在调用时,向匿名函数传递参数内容。
内部函数
Java中的内部类,提高安全性
1 内部(私有)函数 2 function a(param){ 3 function b(input){ 4 return input * 2; 5 }; 6 return "The result is " + b(param); 7 } 8 9 alert(a(2)); //The result is 4 10 当调用全局函数a ( ) 时,本地函数b ( ) 也会在其内部被调用。由于b ( ) 是本地函数, 11 它在a ( ) 以外的地方是不可见的,所以将b 称之为私有函数。 12 私有函数的优点: 13 有助于确保全局名字空间的纯净性(这意味着命名冲突的机会很小)。 14 私有性 —— 只将一些必要的函数暴露给“外面世界”,并保留属于自己的函数,使它们不为该应用程序的其他部分所用。
返回函数的函数
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>01_几种特殊函数.html</title> 5 6 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 7 <meta http-equiv="description" content="this is my page"> 8 <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 9 10 <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> 11 12 </head> 13 14 <body> 15 This is my HTML page. <br> 16 </body> 17 <script type="text/javascript"> 18 /* 19 * 内部(私有)函数(Java里内部类) 20 * * 保证了私有性 —— 外部不能访问不到(提供了安全性) 21 */ 22 // function fn(){ 23 // var a = "a"; 24 // 25 // function n(){ 26 // var b = "b"; 27 // 28 // alert(a+b); //output ab 29 // } 30 // 31 // return n(); 32 // } 33 // 34 // fn(); //output ab 35 36 /* 37 * (了解)返回函数的函数(内部函数的一种特殊用法) 38 * * 可以在全局域中,访问到局部变量的值 39 * * 定义一个函数时,最终执行两个逻辑代码块 40 */ 41 function fn(){ 42 //逻辑代码块 43 var a = "a"; 44 45 return function(){ 46 //逻辑代码块 47 return a; 48 } 49 } 50 51 alert(fn()); //output function(){return a;} 52 53 //var fun = fn(); 54 //var fun = function(){return a;} 55 56 //alert(fun()); //output a 57 58 alert(fn()()); //output a 59 60 /* 61 * javascript中的特殊函数,不是必要使用的内容 62 * * 第一次完成实现逻辑内容时,很少会用到特殊函数 63 * * 在做代码优化的时候,会使用特殊函数 64 * 65 * 代码实现:一次性做到代码最优 66 * * 实现逻辑内容 67 * * 代码优化 68 */ 69 70 </script> 71 </html>
作用域链
1 javascript不存在大括号级的作用域,但具有函数作用域。 2 在函数内定义的变量在函数外是不可见的。但如果该变量是在某个代码块中定义的(如在某个if或for语句中),它在代码块外是可见的。 3 4 var a = 1; 5 function f(){ 6 var b = 2; 7 return a; 8 } 9 10 alert(f()); //output 1 11 alert(b); //output b is undefined 12 13 变量a 是属于全局域的,变量b 的作用域是属于函数f ( ) 内。 14 在f ( ) 内,a 和b 都是可见的。 15 在f ( ) 外,a 是可见的,b 则是不可见的。 16 17 var a = 1; 18 function f(){ 19 var b = 2; 20 function n(){ 21 var c = 3; 22 alert(a); //output 1 23 alert(b); //output 2 24 alert(c); //output 3 25 } 26 return n(); 27 } 28 f(); 29 30 函数n ( ) 可以访问的变量可以是自身的作用域,也可以是其“父级”的作用域。这就形成了一条作用域链 31 function f1(){ 32 var a = 1; 33 f2(); 34 } 35 function f2(){ 36 return a; 37 } 38 39 alert(f1()); //output a is undefined 40 41 在定义函数f1 ( ) 和f2 ( ) 时,只能访问全局作用域和其自身的作用域。 42 在定义函数f2 ( ) 时,变量a 是不可见的。 43 44 var a = 5; 45 function f1(){ 46 var a = 1; 47 f2(); 48 } 49 function f2(){ 50 return a; 51 } 52 53 alert(f1()); //output 5 54 55 在定义函数f1 ( ) 和f2 ( ) 时,都是可以访问全局作用域的。 56
闭包:
定义:
指的是词法表示包括不被计算的变量的函数,也就是说,函数可以使用函数之外定义的变量。
闭包的实现:
1 var b; 2 function a(){ 3 var a = "a"; 4 b = function(){ 5 return a + "b"; 6 } 7 return a; 8 } 9 10 //测试 11 alert(a()); //output a 12 alert(b()); //output ab
在a ( ) 函数中定义了 b ( ) 函数,所以b ( ) 函数可以访问a ( ) 函数的作用域。
将 b ( ) 函数升级到全局函数,但依然保留可以对a ( ) 函数作用域的访问权。
1 function f(){ 2 var a = []; 3 var i; 4 for(i = 0; i < 3; i++){ 5 a[i] = function(){ 6 return i; 7 } 8 } 9 return a; 10 } 11 12 var fun = f(); 13 14 alert(fun[0]()); //output 3 15 alert(fun[1]()); //output 3 16 alert(fun[2]()); //output 3
按照预期,最终结果应该输出 [0 , 1 , 2 ],但是却是[ 3 , 3 , 3 ]。
在函数 f ( ) 中,我们通过循环,创建了三个闭包,它们都指向了共同的局部变量 i 。
但是,闭包并不会记录它们的值,它们所拥有的只是一个 i 的连接(即引用),因此只能返回i 的当前值。
1 function f(){ 2 var a = []; 3 var i; 4 for(i = 0; i < 3; i++){ 5 a[i] = (function(x){ 6 return x; 7 })(i); 8 } 9 return a; 10 } 11 12 var fun = f(); 13 14 alert(fun[0]); //output 0 15 alert(fun[1]); //output 1 16 alert(fun[2]); //output 2
在这里,我们不再直接创建一个返回i 的函数,而是将i 传递给了一个自调函数。
在该自调函数中,i 就被赋值给了局部变量x ,这样一来,每次迭代中的x 就会拥有各自不同的值了。
1 function f(){ 2 function n(x){ 3 return x; 4 } 5 var a = []; 6 var i; 7 for(i = 0; i < 3; i++){ 8 a[i] = n(i); 9 } 10 return a; 11 } 12 13 var fun = f(); 14 15 alert(fun[0]); //output 0 16 alert(fun[1]); //output 1 17 alert(fun[2]); //output 2
上面这种,是不使用自调函数的用法。
对象:
* 定义对象:
* 普通对象
* new Object()
* var 对象名 = {
属性名 : 属性值,
方法名 : function(参数){}
}
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>01_如何定义对象.html</title> 5 6 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 7 <meta http-equiv="description" content="this is my page"> 8 <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 9 10 <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> 11 12 </head> 13 14 <body> 15 This is my HTML page. <br> 16 </body> 17 <script type="text/javascript"> 18 //1 在javascript中,底层存在Object对象:Object对象应该所有对象的父级. 19 var obj1 = new Object(); 20 21 //2 JSON的key/value格式,Java中的Map集合 22 var ob2 = {}; 23 24 //3 在javascript中,函数即对象:函数对象(我起的) 25 function obj3(){} 26 27 </script> 28 </html>
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>02_定义对象的属性和方法.html</title> 5 6 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 7 <meta http-equiv="description" content="this is my page"> 8 <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 9 10 <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> 11 12 </head> 13 14 <body> 15 This is my HTML page. <br> 16 </body> 17 <script type="text/javascript"> 18 //定义普通对象的属性和方法(JSON的key/value格式) 19 var hero = { 20 name : "zhangwuji", 21 sayMe : function(){ 22 alert("i am zhangwuji."); 23 } 24 } 25 26 //定义函数对象的属性和方法 27 function Hero(){ 28 this.name = "zhangwuji"; 29 this.sayMe = function(){ 30 alert("i am zhangwuji."); 31 } 32 } 33 34 /* 35 * this的用法: 36 * * 指代DOM对象 37 * * 指代jQuery对象 38 * * 指代javascript对象 39 */ 40 41 42 </script> 43 </html>
函数对象
function 对象名(参数){ this.属性名 = 属性值; this.方法名 = function(参数){} }
调用对象:
* 普通对象: * 调用: * 第一种: * 对象名.属性名; * 对象名.方法名(); * 第二种: * 对象名['属性名']; * 对象名['方法名'](); * 增加: * 对象名.新的属性名 = 新的属性值; * 对象名.新的方法名 = 新的function(){} * 修改: * 对象名.属性名 = 新的属性值; * 对象名.方法名 = 新的function(){} * 删除: * delete 对象名.属性名; * delete 对象名.方法名; * 函数对象: * 概念性理解: * 函数对象的概念,实际上是不存在的 * 函数对象实际上是叫做构造器 * var 对象名 = new 构造器(); * 获取到函数对象(构造器)的属性和方法 * var 对象名 = new 构造器(); * 调用、修改、删除及增加与操作普通对象一致。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>03_调用对象的属性和方法.html</title> 5 6 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 7 <meta http-equiv="description" content="this is my page"> 8 <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 9 10 <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> 11 12 </head> 13 14 <body> 15 This is my HTML page. <br> 16 </body> 17 <script type="text/javascript"> 18 //普通对象 19 // var hero = { 20 // name : "zhangwuji", 21 // sayMe : function(){ 22 // alert("i am zhangwuji."); 23 // } 24 // } 25 26 //调用普通对象hero的属性和方法 27 //1 28 // alert(hero.name); 29 // hero.sayMe(); 30 31 //2 32 // alert(hero['name']); 33 // hero['sayMe'](); 34 35 //增加普通对象hero的属性和方法 36 //hero.value = "zhouzhiruo"; 37 //alert(hero.value); 38 // hero.sayVal = function(){ 39 // alert("zhangwuji's value is zhouzhiruo."); 40 // } 41 // hero.sayVal(); 42 43 //修改普通对象hero的属性和方法 44 //hero.name = "zhouzhiruo"; 45 //alert(hero.name); 46 // hero.sayMe = function(){ 47 // alert("i am zhouzhiruo.") 48 // } 49 // hero.sayMe(); 50 51 //删除普通对象hero的属性和方法 52 // delete hero.name; 53 // alert(hero.name); 54 55 // delete hero.sayMe; 56 // hero.sayMe(); 57 58 /* 59 * 函数对象:类似于Java中的类的概念 60 * * 实际上,是不存在函数对象的概念的(是我们自己起的名) 61 * * 函数对象实际上是叫做构造器 62 */ 63 function Hero(){ 64 this.name = "zhangwuji"; 65 this.sayMe = function(){ 66 alert("i am zhangwuji."); 67 } 68 } 69 70 /* 71 * 调用之前,必须要先new对象 72 * * 这里的写法是构造函数的写法 73 * * hero也是javascript对象,是一个普通对象 74 */ 75 var hero = new Hero(); 76 77 //调用函数对象Hero的属性和方法 78 // alert(hero.name); 79 // alert(hero['name']); 80 81 // hero.value = "zhouzhiruo"; 82 // alert(hero.value); 83 84 // delete hero.name; 85 // alert(hero.name); 86 87 hero.name = "zhouzhiruo"; 88 alert(hero.name); 89 90 // class A(){ 91 // String name = "zhangwuji"; 92 // } 93 // 94 // A a = new A(); 95 // a.name 96 97 </script> 98 </html>
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>04_this的用法.html</title> 5 6 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 7 <meta http-equiv="description" content="this is my page"> 8 <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 9 10 <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> 11 12 </head> 13 14 <body> 15 This is my HTML page. <br> 16 </body> 17 <script type="text/javascript"> 18 /* 19 * this的用法: 20 * * 指代DOM对象(常用) 21 * * 指代JQuery对象(最不常用) 22 * * 指代javascript对象(居中) 23 * 24 * this的实际用法,不止以上三种. 25 */ 26 //1 指代DOM对象 27 // document.getElementById("ok").onclick = function(){ 28 // this.value; 29 // } 30 31 //2 指代jQuery对象:在jQuery的插件中使用 32 $.each(this,function(){ 33 alert(this.value); 34 }); 35 36 //3 指代javascript对象:只要在函数对象中,使用this的话,this永远都指代函数对象 37 function Hero(){ 38 this.name = "zhangwuji"; 39 this.sayMe = function(){ 40 alert("hello "+this.name); 41 } 42 } 43 44 var hero = new Hero(); 45 46 hero.sayMe(); 47 48 </script> 49 </html>
内建对象:
* 数据封装类对象 * String、Array、Number等 * 工具类对象 * Date、Math等 * 错误类对象 * Error、异常对象等 * 在javascript中,只有对象(变量、方法、集合等) * javascript是更纯粹的面向对象
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>05_举例.html</title> 5 6 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 7 <meta http-equiv="description" content="this is my page"> 8 <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 9 10 <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> 11 12 </head> 13 14 <body> 15 This is my HTML page. <br> 16 </body> 17 <script type="text/javascript"> 18 //定义一个字符串 19 var str = "aaaa"; 20 //定义一个数值 21 var i = 7; 22 //定义一个数组 23 var arr = [1,2,3,4,5]; 24 25 /* 26 * 这些所谓的常用类型,可以直接使用 27 * * 这种方式类似于Java中JDK提供的常用类型 28 * * 说明在javascript的底层,提供了类似的常用类型 29 * 30 * javascript的内建对象:Java中的API提供的常用类型 31 * * javascript内建对象:帮助文档"w3school.chm" 32 * * javascript的内容并不像java一样,具有完整的帮助文档.(javascript没有完整的帮助文档) 33 */ 34 35 </script> 36 </html>
Array:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>02_Array对象.html</title> 5 6 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 7 <meta http-equiv="description" content="this is my page"> 8 <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 9 10 <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> 11 12 </head> 13 14 <body> 15 This is my HTML page. <br> 16 </body> 17 <script type="text/javascript"> 18 //以下两种写法是等价的 19 var arr1 = []; 20 var arr2 = new Array(); 21 22 alert(typeof arr1); //object 23 alert(typeof arr2); //object 24 25 //Array对象的属性 26 //1 length属性:获取数组长度 27 //alert(arr1.length); 28 29 //2 index和input属性,放弃的 30 31 //3 constructor属性:返回对创建此对象的数组函数的引用。(不研究) 32 33 //4 prototype属性:使您有能力向对象添加属性和方法。(现在不研究,统一放在原型的内容) 34 35 //Array对象的方法 36 //1 toString()方法:把数组转换为字符串,并返回结果。 37 38 //2 join()方法:把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。 39 40 //3 pop()和push()方法:删除并返回数组的最后一个元素;向数组的末尾添加一个或更多元素,并返回新的长度。 41 42 //4 reverse()方法:颠倒数组中元素的顺序。 43 44 //javascript的内建对象的属性和方法,在Java中的JDK的内容,都有类似的内容 45 46 //反转字符串示例(面试题) 47 48 //定义一个字符串 49 var str = "abcdefg"; 50 //利用String对象的split()方法,将字符串切割成一个数组 51 var arr = str.split(""); 52 //利用Array对象的reverse()方法,将数组中元素的顺序颠倒。 53 arr = arr.reverse(); 54 //测试打印 55 alert(arr.toString()); 56 57 //Java的版本至少在1.5版本以上 58 59 60 </script> 61 </html>
String:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>03_String对象.html</title> 5 6 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 7 <meta http-equiv="description" content="this is my page"> 8 <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 9 10 <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> 11 12 </head> 13 14 <body> 15 This is my HTML page. <br> 16 </body> 17 <script type="text/javascript"> 18 //以下两种写法不是等价的(面试) 19 var str1 = "aaa"; 20 // var str2 = new String("aaa"); 21 // 22 // alert(typeof str1); //string 23 // alert(typeof str2); //object 24 25 //String对象的属性 26 //length属性:字符串的长度(字符的个数) 27 //alert(str1.length); //3 28 29 //String对象的方法 30 //1 substr():从起始索引号提取字符串中指定数目的字符。 31 //2 substring():提取字符串中两个指定的索引号之间的字符。 32 33 //3 split():把字符串分割为字符串数组。 34 35 //4 replace():替换与正则表达式匹配的子串。 36 37 //判断字符串是否包含指定字符串示例 38 39 //定义两个要判断的字符串 40 var str = "abcdefg"; 41 var substr = "xyz"; 42 43 function sub(str,substr){ 44 //将判断的字符串定义成String对象 45 var string = new String(str); //不必要,更规范一些 46 //截取判断的字符串 47 var result = string.substr(string.indexOf(substr),substr.length); 48 49 if(result==substr){ 50 return true; 51 }else{ 52 return false; 53 } 54 } 55 56 alert(sub(str,substr)); 57 58 </script> 59 </html>
Events对象:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>04_Events对象.html</title> 5 6 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 7 <meta http-equiv="description" content="this is my page"> 8 <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 9 10 <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> 11 12 </head> 13 14 <body> 15 This is my HTML page. <br> 16 </body> 17 <script type="text/javascript"> 18 /* 19 * Event:事件 20 * Events对象:事件对象 21 * * 在javascript中,具有事件的. 22 * onclick\ondblclick\onchange等 23 * * 事件对象与之前使用的事件内容,是否存在关系? 24 * 之前使用的事件内容,其实是javascript中事件对象的属性. 25 */ 26 27 28 29 </script> 30 </html>
Functions对象
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>05_Functions对象.html</title> 5 6 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 7 <meta http-equiv="description" content="this is my page"> 8 <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 9 10 <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> 11 12 </head> 13 14 <body> 15 This is my HTML page. <br> 16 </body> 17 <script type="text/javascript"> 18 /* 19 * Functions对象:javascript全局对象 20 * * 全局属性: 21 * * NaN:表示不是一个数值 22 * * undefined:未定义 23 * * 全局方法 24 * * decodeURI():解码某个编码的 URI。 25 * * encodeURI():把字符串编码为 URI。 26 * * escape():对字符串进行编码。 27 * * eval():计算 JavaScript 字符串,并把它作为脚本代码来执行。 28 * * isNaN():检查某个值是否是数字。返回值为Boolean值,true不是数字. 29 * 30 * Functions对象与Function对象:是不是一个? 31 * * Function对象实际上,浏览器内核中集成的javascript引擎里. 32 * * 对于Function对象,我们只需要了解new Function()定义函数即可. 33 */ 34 35 36 37 38 </script> 39 </html>
Object对象:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>01_Object对象.html</title> 5 6 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 7 <meta http-equiv="description" content="this is my page"> 8 <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 9 10 <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> 11 12 </head> 13 14 <body> 15 This is my HTML page. <br> 16 </body> 17 <script type="text/javascript"> 18 //以下两种写法是等价的(面试题) 19 var obj1 = new Object(); 20 var obj2 = {}; 21 22 //Object对象是所有javascript对象的父级. 23 24 //面试题(真实) 25 //判断以下哪个描述是错误的?D 26 // var a = {}; //定义对象 27 // var b = []; //定义数组 28 // var c = //; //定义正则表达式 29 // var d = (); 30 31 //面试题(百度) 32 //alert():提示框,在提示框中实现换行 33 alert("xxx\nyyy"); 34 35 36 </script> 37 </html>
更多参考W3cSchool帮助文档
原型(prototype)
及其重要(作用)
* 定义:原型就是一个函数对象的属性。(记住是函数对象function XXX{ name:xxx...... })
* 作用:
* 利用原型为函数对象增加属性和方法
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>01_研究函数对象的原型属性.html</title> 5 6 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 7 <meta http-equiv="description" content="this is my page"> 8 <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 9 10 <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> 11 12 </head> 13 14 <body> 15 This is my HTML page. <br> 16 </body> 17 <script type="text/javascript"> 18 //原型是函数对象的一个属性(普通对象是没有原型属性的.). 19 function Hero(){ 20 this.name = "zhangwuji"; 21 this.sayMe = function(){ 22 alert("i am zhangwuji."); 23 } 24 } 25 26 //调用函数对象Hero的属性和方法:new Hero() 27 var hero = new Hero(); 28 29 //调用函数对象Hero的属性或方法时,实际上调用new之后的hero对象. 30 //alert(hero.name); 31 32 //调用函数对象的原型属性,是应该调用Hero对象还是hero对象呢? 33 //hero.prototype; 34 Hero.prototype; 35 36 37 38 39 </script> 40 </html>
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>02_利用原型增加函数对象的属性或方法.html</title> 5 6 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 7 <meta http-equiv="description" content="this is my page"> 8 <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 9 10 <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> 11 12 </head> 13 14 <body> 15 This is m 16 <script type="text/javascript"> 17 // function Hero(){ 18 // this.name = "zhangwuji"; 19 // this.sayMe = function(){ 20 // alert("i am zhangwuji."); 21 // } 22 // } 23 24 //普通对象 25 // var hero = new Hero(); 26 27 //hero.value = "zhouzhiruo"; 28 29 //利用原型为函数对象增加属性或方法. 30 //函数对象.prototype.新的属性名 = 新的属性值; 31 //Hero.prototype.value = "zhouzhiruo"; 32 33 //alert(hero.prototype.value); //output zhouzhiruo 34 //alert(hero.value); 35 36 // Hero.prototype.sayVal = function(){ 37 // alert("i am zhouzhiruo."); 38 // } 39 // 40 // alert(hero.sayVal()); 41 42 //利用原型增加的属性和方法与上午说的增加属性和方法的区别?利用原型增加属性和方法更优 43 //1 定义一个函数对象 44 function Hero(){ 45 this.name = "zhangwuji"; 46 this.sayMe = function(){ 47 alert("i am zhangwuji."); 48 } 49 } 50 51 //2 (分散形式)利用原型增加属性和方法 52 // Hero.prototype.value = "zhouzhiruo"; 53 // Hero.prototype.sayVal = function(){ 54 // alert("i am zhouzhiruo."); 55 // } 56 57 //学习JSON时 58 // var method = { 59 // add : function(a,b){ 60 // return a+b; 61 // } 62 // } 63 64 /* 65 * (集中方式)将增加属性和方法的内容,集中写在一起 66 * * 格式:函数对象.prototype = 新的对象 67 * * 注意:只能先增加,再new对象 68 * (分散形式) 69 * * 先new对象和后new对象,没有关系 70 */ 71 Hero.prototype = { 72 value : "zhouzhiruo", 73 sayVal : function(){ 74 alert("i am zhouzhiruo."); 75 } 76 } 77 78 //3 new对象 79 var hero = new Hero(); 80 81 //4 测试 82 alert(hero.value); 83 hero.sayVal(); 84 85 </script> 86 </html>
* 函数对象的属性或方法与原型的属性或方法同名时:
* 函数对象本身的属性和方法的优先级要高于原型上的熟悉感和方法
* 利用函数对象的属性和方法重写原型上的属性和方法
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>03_函数对象的属性或方法与原型的属性和方法同名.html</title> 5 6 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 7 <meta http-equiv="description" content="this is my page"> 8 <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 9 10 <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> 11 12 </head> 13 14 <body> 15 This is my HTML page. <br> 16 </body> 17 <script type="text/javascript"> 18 /* 19 * 函数对象的属性或方法与原型的属性或方法同名时: 20 * * 调用的属性和方法,是函数对象的属性和方法 21 * * 函数对象本身的属性和方法与原型的属性和方法同时存在 22 * * 函数对象本身的属性和方法的优先级要高于原型上的熟悉感和方法 23 */ 24 function Hero(){ 25 this.name = "zhangwuji"; 26 this.sayMe = function(){ 27 alert("i am zhangwuji."); 28 } 29 } 30 31 //原型增加的属性和方法,到底有没有增加上去呢? 32 Hero.prototype = { 33 name : "zhouzhiruo", 34 sayMe : function(){ 35 alert("i am zhouzhiruo."); 36 } 37 } 38 39 var hero = new Hero(); 40 41 alert(hero.name); //output zhangwuji 42 43 delete hero.name; 44 45 alert(hero.name); //output zhouzhiruo 46 47 48 49 </script> 50 </html>
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>04_利用原型重新定义函数对象.html</title> 5 6 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 7 <meta http-equiv="description" content="this is my page"> 8 <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 9 10 <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> 11 12 </head> 13 14 <body> 15 This is my HTML page. <br> 16 </body> 17 <script type="text/javascript"> 18 //定义一个空的函数对象 19 function Hero(){} 20 21 //函数对象的属性和方法,都定义在原型上 22 Hero.prototype = { 23 name : "zhangwuji", 24 sayMe : function(){ 25 alert("i am zhangwuji."); 26 } 27 } 28 29 </script> 30 </html>
* 内建对象(应该都是函数对象):都有prototype属性
* 可以扩展内建对象的属性和方法
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>05_扩展内建对象的属性和方法.html</title> 5 6 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 7 <meta http-equiv="description" content="this is my page"> 8 <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 9 10 <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> 11 12 </head> 13 14 <body> 15 This is my HTML page. <br> 16 </body> 17 <script type="text/javascript"> 18 // //为原型 Array对象增加一个判断的函数 19 // Array.prototype.inArray = function(color){ 20 // //this指代Array对象 21 // for(var i = 0, len = this.length; i < len; i++){ 22 // //"==="叫全等号:值和类型;"!=="叫全不等号 23 // if(this[i] === color){ 24 // return true; 25 // } 26 // } 27 // return false; 28 // } 29 // 30 // //定义一个Array对象 31 // var a = ["red", "green", "blue"]; 32 // 33 // //测试 34 // alert(a.inArray("red")); //true 35 // alert(a.inArray("yellow")); //false 36 37 function inArray(arr,color){ 38 for(var i = 0, len = arr.length; i < len; i++){ 39 //"==="叫全等号:值和类型;"!=="叫全不等号 40 if(arr[i] === color){ 41 return true; 42 } 43 } 44 return false; 45 } 46 47 var a = ["red", "green", "blue"]; 48 49 alert(inArray(a,"red")); //output true 50 51 /* 52 * 以上两种写法哪种更好? 53 * * (更好)一种通过原型扩展内建对象 54 * * 自定义函数完成需求 55 * 但是,一般不建议大家使用原型来扩展内建对象. 56 * * 扩展内建对象这种方式不好.(内建对象是底层提供的,最好不要修改) 57 * 但是,介绍js库的时候,有prototype. 58 * * 对于javascript原型这个概念,讨论的是比较激烈? 59 * * (A)正面,支持这种用法,代表性的是prototype库. 60 * * (B)反面,不支持. 61 * 关于利用原型扩展内建对象,了解即可. 62 */ 63 64 65 </script> 66 </html>
继承
定义:如果两个类都是同一个实例的类型,那么它们之间存在着某些关系,我们把同一个实例的类型之间的泛化关系称为“继承”。
如果两个类都是同一个实例的类型,那么它们之间存在着某些关系,我们把同一个实例的类型之间的泛化关系称为“继承”。
继承关系至少包含三层含义:
子类的实例可以共享父类的方法。
子类可以覆盖父类的方法或扩展新的方法。
子类和父类都是子类实例的“类型”。
在javascript中,并不支持“继承”。也就是说,javascript中没有继承的语法。从这个意义上来说,javascript并不是直接的面向对象语言。
* 问题: * 在javascript中,是不存在继承的关系的(关键字 extend)! * 在javascript中,没有类的概念。 * javascript就不是一个直接的面向对象语言。 * "继承": * javascript中函数对象与函数对象之间的继承。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>01_利用原型实现继承.html</title> 5 6 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 7 <meta http-equiv="description" content="this is my page"> 8 <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 9 10 <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> 11 12 </head> 13 14 <body> 15 This is my HTML page. <br> 16 </body> 17 <script type="text/javascript"> 18 function A(){ 19 this.a = "a"; 20 this.sayA = function(){ 21 alert("this is a."); 22 } 23 } 24 25 var a = new A(); 26 27 function B(){ 28 this.b = "b"; 29 this.sayB = function(){ 30 alert("this is b."); 31 } 32 } 33 34 B.prototype = a; 35 36 //测试:函数对象B就"继承"了函数对象A 37 var b = new B(); 38 39 // alert(b.b); 40 // b.sayB(); 41 // 42 // alert(b.a); 43 // b.sayA(); 44 45 // b.a = "c"; 46 // b.sayA = function(){ 47 // alert("this is c.") 48 // } 49 // 50 // alert(b.a); 51 // b.sayA(); 52 53 // b.c = "c"; 54 // b.sayC = function(){ 55 // alert("this is c.") 56 // } 57 // 58 // alert(b.c); 59 // b.sayC(); 60 61 </script> 62 </html>
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>02_只继承于原型.html</title> 5 6 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 7 <meta http-equiv="description" content="this is my page"> 8 <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 9 10 <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> 11 12 </head> 13 14 <body> 15 This is my HTML page. <br> 16 </body> 17 <script type="text/javascript"> 18 // function A(){ 19 // this.a = "a"; 20 // this.sayA = function(){ 21 // alert("this is a."); 22 // } 23 // } 24 // 25 // function B(){ 26 // this.b = "b"; 27 // this.sayB = function(){ 28 // alert("this is b."); 29 // } 30 // } 31 // 32 // B.prototype = A.prototype; 33 // 34 // //测试 35 // var b = new B(); 36 // 37 // alert(b.a); 38 // b.sayA(); 39 40 /******************************************/ 41 42 // function A(){} 43 // 44 // A.prototype = { 45 // a : "a", 46 // sayA : function(){ 47 // alert("this is a.") 48 // } 49 // } 50 // 51 // function B(){} 52 // 53 // B.prototype = { 54 // b : "b", 55 // sayB : function(){ 56 // alert("this is b.") 57 // } 58 // } 59 // 60 // B.prototype = A.prototype; 61 // 62 // var b = new B(); 63 // 64 //// alert(b.a); 65 //// b.sayA(); 66 // 67 // alert(b.b); 68 // b.sayB(); 69 70 /***************************************/ 71 72 function A(){} 73 74 A.prototype = { 75 a : "a", 76 sayA : function(){ 77 alert("this is a.") 78 } 79 } 80 81 function B(){ 82 this.b = "b"; 83 this.sayB = function(){ 84 alert("this is b."); 85 } 86 } 87 88 B.prototype = A.prototype; 89 90 var b = new B(); 91 92 alert(b.b); 93 b.sayB(); 94 95 alert(b.a); 96 b.sayA(); 97 98 </script> 99 </html>
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>03_解决多函数对象之间的继承关系.html</title> 5 6 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 7 <meta http-equiv="description" content="this is my page"> 8 <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 9 10 <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> 11 12 </head> 13 14 <body> 15 This is my HTML page. <br> 16 </body> 17 <script type="text/javascript"> 18 function A(){} 19 20 A.prototype = { 21 a : "a", 22 sayA : function(){ 23 alert("this is a.") 24 } 25 } 26 27 function B(){} 28 29 //这种方式利用原型为函数对象B增加属性和方法(集中方式) 30 // B.prototype = { 31 // b : "b", 32 // sayB : function(){ 33 // alert("this is b.") 34 // } 35 // } 36 37 //分散形式 38 // B.prototype.b = "b"; 39 // B.prototype.sayB = function(){ 40 // alert("this is b.") 41 // } 42 43 /* 44 * 分析得出这句话出问题了 45 * * 因为B.prototype多次调用 46 * * 出现的顺序有关系?谁先定义,谁被覆盖 47 * * 原型定义属性和方法的形式有关系?没有关系 48 */ 49 B.prototype = A.prototype; 50 51 // B.prototype = { 52 // b : "b", 53 // sayB : function(){ 54 // alert("this is b.") 55 // } 56 // } 57 58 /* 59 * 条件: 60 * * 先实现函数对象B"继承"函数对象A的内容 61 * * 再利用原型为函数对象B增加属性和方法(分散形式) 62 */ 63 B.prototype.b = "b"; 64 B.prototype.sayB = function(){ 65 alert("this is b.") 66 } 67 68 var b = new B(); 69 70 alert(b.a); 71 b.sayA(); 72 73 alert(b.b); 74 b.sayB(); 75 76 77 78 79 </script> 80 </html>
原型链
1 原型链是ECMAScript标准制定的默认继承方式。 2 function A(){ 3 this.name = "a"; 4 this.toString = function(){return this.name}; 5 } 6 function B(){ 7 this.name = "b"; 8 } 9 function C(){ 10 this.name = "c"; 11 this.age = 18; 12 this.getAge = function(){return this.age}; 13 } 14 15 B.prototype = new A(); 16 C.prototype = new B(); 17 将对象直接创建在B对象的prototype属性中,并没有去扩展这些对象的原有原型。 18 通过new A ( ) 另创建了一个新的实体,然后用它去覆盖该对象的原型。 19 javascript是一种完全依靠对象的语言,其中没有类(class)的概念。 20 因此,需要直接用new A ( ) 创建一个实体,然后才能通过该实体的属性完成相关的继承工作。 21 完成这样的继承实现之后,对 A ( ) 所进行的任何修改、重写或删除,都不会对 B ( ) 产生影响。 22 23 只继承于原型: 24 function A(){} 25 A.prototype.name = "a"; 26 A.prototype.toString = function(){return this.name}; 27 28 function B(){} 29 B.prototype = A.prototype; 30 B.prototype.name = "b"; 31 32 function C(){} 33 C.prototype = B.prototype; 34 C.prototype.name = "c"; 35 C.prototype.age = 18; 36 C.prototype.getAge = function(){return this.age}; 37 38 对象之间的继承(扩展内容,可以不会)(浅复制) 39 //该函数接受一个对象并返回它的副本 40 function extendCopy(p){ 41 var z = {}; //定义一个空的对象z 42 for(var i in p){ //var i =0 ; i < p.length ; i++ 43 z[i] = p[i]; //都当做数组处理的话,可以理解 44 } 45 //uber属性:将p作为z的父级,将z指向p的原型 46 z.uber = p; 47 return z; 48 } 49 //定义对象a,但是对象a不是函数对象 50 var a = { 51 name : "a", 52 toStr : function(){return this.name;} 53 } 54 //定义对象b,但是对象b不是函数对象 55 var b = extendCopy(a); 56 b.name = "b"; 57 b.toStr = function(){return this.uber.toStr() + " , " + this.name;}; 58 //定义对象c,但是对象c不是函数对象 59 var c = extendCopy(b); 60 c.name = 18; 61 62 alert(c.toStr()); //output a , b , 18
* (了解)javascript中的普通对象之间,是否也存在"继承"关系呢?存在
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>04_普通对象之间的继承.html</title> 5 6 <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> 7 <meta http-equiv="description" content="this is my page"> 8 <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 9 10 <!--<link rel="stylesheet" type="text/css" href="./styles.css">--> 11 12 </head> 13 14 <body> 15 This is my HTML page. <br> 16 </body> 17 <script type="text/javascript"> 18 //对象之间的继承 19 20 //该函数接受一个对象并返回它的副本 21 function extendCopy(p){ 22 var z = {}; //定义一个空的对象z 23 for(var i in p){ //var i =0 ; i < p.length ; i++ 24 z[i] = p[i]; //都当做数组处理的话,可以理解 25 } 26 //uber属性:将p作为z的父级,将z指向p的原型 27 z.uber = p; 28 return z; 29 } 30 //定义普通对象a,但是对象a不是函数对象 31 var a = { 32 name : "a" 33 } 34 //暂且将b也当作普通对象来看待 35 var b = extendCopy(a); 36 b.toStr = function(){return this.name;}; 37 38 alert(b.toStr()); //output a 39 40 </script> 41 </html>