AI写作智能体 自主规划任务,支持联网查询和网页读取,多模态高效创作各类分析报告、商业计划、营销方案、教学内容等。 广告
## **1.****程序异常** ### **①****try-catch****语法****测试异常** **try-catch**语法代码如下:          **try**{              异常代码;     try中可以承重异常代码,            console.log(“try”)  出现异常代码后,正确代码不会执行 }**catch**(**e**) { console.log(“e:”+**e**);  try中出现异常在**e**中展现出来               console.log(“catch”);  只有try中出现异常才执行这段代码 }**finally**{ console.log( 1 );  无论try中有无异常,都会执行finally代码 } ### **②****throw****语法****抛出异常** throw(name: ”Tom”, age: 18)    抛出异常,抛出一个对象 ## **2. ****函数的预解析** 代码如下:     console.log(**fn1**);     console.log(**fn2**);     var**fn1**\= function () {};     function**fn2**(){} 表达式式函数:     var**fn1**\= function () {};   **用****”****;****”****结尾** 特点:没有函数名,预解析过程var fn1声明提升,”=”号的赋值没有执行,console.log(fn1)结果为undefined; 声明式函数:       function**fn2**(){}     **不用****”****;****”****结尾** 特点:有函数名(fn2),预解析过程已经将函数体赋值给了fn2,console.log(fn2)结果为function fn2(){} ## **3. ****作用域经典问题**     var  arr = \[ { name: 'Tom' },         { name: 'Jack' },         { name: 'Jim' },         { name: 'Lily' } \];     for ( var i = 0; i < arr.length; i++) {         arr\[ i \].sayHello = function () {             console.log( 'name = ' +**arr\[ i \]**.name );         };     }     for ( var j = 0; j < arr.length; j++ ) {         arr\[ j \].sayHello(); } 代码执行会报错,因为当执行arr\[j\].sayHello()时,函数中**arr\[i\]**.name才执行,此时i的值已经为4了,如果把代码改为:     for ( var i = 0; i < arr.length; i++ ) {         arr\[ i \].sayHello(); } 则可以顺利执行,因为调用函数sayHello()时,对i进行了重新赋值,进入函数作用域内后**arr\[i\]**也就变为动态变化的值了 **该问题的由来,代码如下:**                          ①                  ②                  ③                  ④                  ⑤                 var list = document.getElementsByTagName( 'li' );         var i;         for ( i = 0; i < list.length; i++ ){                  list\[ i \].onclick = function () {                           alert(**list\[ i \]**.innerHTML );  **点击进入函数作用域时****i****的值已经为****5****了** **            alert( this.innerHTML );  ****将****list\[i\]****改为****this****,可以正常执行**                  };         } ## **4.****函数相关参数** ### **① ****arguments**  **arguments**: 函数中默认的类似**数组类型**对象,里面存储了所有传入的**参数** ### **② ****函数名****.length** 函数中所有参数的个数,若无参数则为0; 综合使用案例,封装一个extend扩展函数,代码如下:     function**extend**() {      **这种写法,只支持最多传入两个参数**         var args =**arguments**;         if (args**.length**\== 1) {             for (var k in args\[0\]) {                 this\[k\] = args\[0\]\[k\];             }         } else {             for (var k in args\[1\]) {                         args\[0\]\[k\] = args\[1\]\[k\];             }         }     }     var o1 = {name: "Tom"};     var o2 = {age: 18, gender: "male"};     var o3 = {goHome: "bus"};    **extend**(o1, o2);    **将****o2****混入****o1****之中**     o3.**extend**\=**extend;**     o3.**extend**(o1);    **将****o1****添加到****o3****之中** console.log(o3); ### **③ ****callee****与****caller** **(****1****)****callee****:****当前函数的引用** **语法:****arguments.callee**     function**foo**() {         console.log(**arguments.callee**\===**foo**); **返回值为****true**     } **foo**(); **callee**一般在函数内部,实现函数递归时,使用callee表示函数引用 **(****2****)****caller:****表示在****fn1****中调用****fn2    ****兼容性不佳** **语法:****函数名****.caller   **     function**fn1**() {         console.log(**fn1.caller**);  **打印调用者****fn2****,打印结果如下:** }                                                       function fn2() { fn1() };     function**fn2**() {        **fn1**();     } **fn2**(); ## **5.****eval(“ ”)****:动态执行函数** ### **①****eval****(“var num=12;” )****函数中的声明会在整个作用域起作用** ### **②****eval()****与****Function()****的比较** **eval:**直接调用就执行eval(“alert(“执行”);”),代码执行 **Function:**需要调用才执行,var **fn**\= new Function(“alert(“执行”)”),这个过程是生成了一个函数,调用函数**fn()**;代码执行,**函数内声明只会在函数内起作用** **使用****Function****的立即执行函数(自调用函数):** **(****new Function(“alert(“****执行****”)” )) ();****对函数使用****(****函数****)();**括号结构相当于执行了函数 任意函数的立即执行:    **(**function**fn**(){         alert("立即执行"); }**)()**; ### **③****将****json****字符串转换成对象** 不严格的**json**格式(属性没有写双引号””)但js能够识别如下:  var**data**\='\[{name:"Tom",age:18,gender:"male"},{name:"Jim",age:20,gender:"male"\]'; #### **(****1****)使用****eval();****传入****json****使用****( )****括起来** var obj =**eval**(“**(**”**+data+**”**)**”);    转换后obj为json对象 **\*****使用****eval()****为何需要将****data****用圆括号括起来****( )****,变成表达式:** **a )****标识符**格式:**任意名****+****:**,例如:**label:** **标识符的使用:** **  label:**             while (true) {                 console.log("第一层循环");                 while (true) {                     console.log("第二层循环");                     while (true) {                         console.log("第三层循环");                      **  break label;**                         console.log("第三层循环");                     }                                                 console.log("第二层循环");                 }                 console.log("第一层循环");             }            ![](https://images2015.cnblogs.com/blog/1071151/201702/1071151-20170225002940413-914916119.png) 执行结果如上图所示,使用标识符后,从第三层循环直接跳出所有循环 **b ) ****eval()****中添加括号的解释:**  var**s1**\= '{ }'; var o1 = eval(**s1**); console.log(o1)**没有任何结果****undefined** var**s2**\= '{name: "Tom"}'; var o2 = eval(**s2**); console.log(o2)**输出****”****Tom****”**  var**s3**\= '{name: "Tom" , age: 18}';     var o3 = eval(**s3**);     console.log(o1)**直接报错** **出现这种现象的原因是,****eval( )****将****{ }****当做代码块来执行,****o2****中的****name:****被当做标识符所以输出****”Tom”****,而****o3****中的****name:****, age****:****被判定为用****”****,****”****号分割的标识符,是错误代码,所以直接报错,若将****o3****改为****o3=****eval(‘{name: “Tom”****;****a****ge: 18}’)****,使用****”****;****”****号分割,则输出****18****,原因是系统默认****age:****标识符替换了****name:****标识符,所以最后解决这个问题的办法是用****( )****将代码括起来,变成表达式,再给****eval( )****解析** #### **(****2****)使用****Function** var obj = (new**Function**(‘return’**+data**))(); #### **(****3****)使用标准处理:****JSON.parse()****; ****该方法必须使用严格的****json****格式,即属性必须写双引号****””** var**data**\='\[{"name":"Tom","age":18,"gender":"male"},{"name":"Jim","age":20,"gender":"male"\]' var obj =**JSON.parse**(**data**); ## **6.****函数的四种调用模式** ### **①****函数调用模式****  func()** 函数名+();        function**func**() {         console.log(**this**);     } **func**(); ![](https://images2015.cnblogs.com/blog/1071151/201702/1071151-20170227153742813-701392066.png) 函数是window  **this**指向window ### **②****方法调用模式****  obj.func()** **宿主对象****obj****调用函数,****this****指向引导方法的对象**     function**func**() {         console.log(this);     }    **func**();     var obj = {name: "object"};     obj.**func**\=**func**; obj.**func**(); ![](https://images2015.cnblogs.com/blog/1071151/201702/1071151-20170225003222210-761781329.png) func():函数调用模式**this**指向window,obj.func():方法调用模式**this**指向obj ### **③****构造器调用模式(****constructor****)****使用****new****关键字引导** **new**是一个运算符,专门用来申请创建对象,创建出的对象传递给构造函数的**this**,利用构造函数对其初始化 #### **(****1****)构造函数创建对象时的返回值(打印对象)** **如果构造函数没有设置参数,在创建对象时****( )****可以不写,例如:** **var obj = newPerson****;****这样写即可** a ) 如果没有写返回值默认返回**this**     function**Person**() {         this.name = "Tom";         this.age = 18;         this.gender = "male";     } var obj=new**Person**(); console.log(obj);             Person {name: "Tom" , age: 18 , gender: "male"} b ) 如果返回值是基本数据类型**,****number**或**string****,**则忽略返回类型,返回**this**   function**Person**() {         this.name = "Tom";         this.age = 18;         this.gender = "male";         return "string"**||**123;            }  var obj=new**Person**();  console.log(obj);          Person {name: "Tom" , age: 18 , gender: "male"} c ) 如果返回值是引用数据类型,\[ \]或者{ },则忽略**this**,返回该数据类型   function**Person**() {         this.name = "Tom";         this.age = 18;         this.gender = "male";         return \[ \]**||**{ };  /  **return { } || \[ \]**      }     var obj=new**Person**();     console.log(obj);      \[ \]  /** { }** #### **(****2****)综合分析题,代码如下:**     function**Foo**(){        **getName**\= function(){ alert(1); };         return**this**;     }   ** Foo**.**getName**\= function(){ alert(2); };   ** Foo**.prototype.**getName**\= function(){ alert(3); };     var**getName**\= function(){ alert(4); };     function**getName**(){ alert(5); } **Foo**.**getName**();           **2** 方法调用,只有alert(2)是该方法调用 **getName**();              **4** 函数声明提前,最后赋值为alert(4) **Foo**().**getName**();         **1** Foo()函数调用,返回window,进入函数体,getName赋值为alert(1),且被window调用,等于函数调用模式 **getName**();             **1**函数调用模式,在上步已经赋值为alert(1) **new****Foo****.getName**();       **2**创建Foo.getName()构造函数的对象,等于该方法调用alert(1) **new****F****oo**().**getName**();     **3**  new与()相结合,等于new Foo()构造函数创建的对象{}调用getName,由于构造函数没有定义getName属性,但是定义了Foo.prototype.getName,所以该对象{}继承了自己原型对象的getName属性alert(3) **new new****Foo**().**getName**();  **3**同上步,new Foo()构造函数创建的对象{},所以该代码相当于new {}.getName(等于{}的方法调用模式创建对象,同理上一步,到Foo的原型对象找getName属性alert(3),这一步与上一步的区别是,上一步最后执行方法调用函数,这一步最后以上一步执行的方法调用函数为构造函数,创建对象 ### **④****上下文(环境)调用模式****apply****、****call** #### **(****1****)****apply  ****参数以数组形式传入** **a )apply****只传一个对象的函数调用**     function**fn**() {         console.log(this);     }     var obj = {name: "Tom", age: 18};    **fn**();    **fn**.**apply**(**null**);    **apply****中传入一个****null****或者不传参数    ****apply( )****,等于函数调用模式**     obj.func =**fn**;     obj.**func**();    **fn.apply**(obj);   **apply****中传入一个对象,等于该对象的方法****调用模式** 上面代码的运行结果为: ![](https://images2015.cnblogs.com/blog/1071151/201702/1071151-20170225004351335-99053732.png) **fn()**与**fn.apply(****null****)**等价,**obj****.func()**与**fn.apply(****obj****)**等价 **b )apply****传入参数的函数调用****数组参数** **语法**: function**fn**(**argu1**,**argu2**) { }; **函数** **fn.apply**(**obj**, \[**argu1**,**argu2**\] ) 示例代码如下:     function**fn**(**num1**,**num2**) {         console.log(this);         return**num1**+**num2**;     }     var obj = {name: "Tom", age: 18};     obj.func =**fn**;     console.log(obj.func( 123 , 456 ) );     console.log(**fn.apply**(**obj**, \[123, 456\] ) ); **c )apply****使用案例** **一、 ****合并数组:**     var arr1 = \[1, 2, 3\];     var arr2 = \[4, 5\];     arr1.push(arr2\[0\],arr2\[1\]);   ** \[ \]**.push.**apply**(arr1,arr2);   **这个方法与上面的方法等价** **二、 ****合并标签对象:** 这是div标签1 这是div标签2 这是p标签1 这是p标签2 **将上述****4****个标签对象放入一个数组之中:**     va**rbyTag**\=**document**.getElementsByTagName,**arr=\[ \];**   ** arr.**push.**apply**(**arr**,**byTag**.**apply**(**document**, \["div"\]));   ** arr.**push.**apply**(**arr****,byTag**.**apply**(**document**, \["p"\]));     console.log(**arr**); 由于getElementsByTagName( )是**document**的方法调用函数,所以过byTag获取该方法后,该方法必须在document对象下调用,所以在apply中传入**document**对象 **(****2****)****call****参数以独立形势传入** **call****用法与****apply****除了参数传入形势不同以外,其他基本相同** **语法**: function**fn**(**argu1**,**argu2**) { };**函数** **fn.call****(obj , argu1 , argu2**) 借用构造方法创建对象:     function**Person**(**name, age, gender**) {       ** this**.name =**name**;        **this**.age =**age;**        **this**.gender =**gender;**     }     function**Student**(**name,age,gender,course**) {       ** Person.call**(**this**,**name, age, gender**);        **this**.course =**course**;     }     var student=new**Student**("Tom",20,"male","Math");     console.log(student); ## **7.****补充知识** ### **①****bind****调用****让函数绑定对象的一种方法,在调用函数时,就像是该对象在调用方法** **语法:函数****.bind**(**对象**),返回一个**函数** **下列代码:**     va**rbyTag**\=**document**.getElementsByTagName,**arr=\[ \];**   ** arr.**push.**apply**(**arr**,**byTag**.**apply**(**document**, \["div"\]));   ** arr.**push.**apply**(**arr****,byTag**.**apply**(**document**, \["p"\]));     console.log(**arr**); **使用****bind****对代码进行修改:** var**bindT****\=document**.getElementsByTagName.**bind****(document),arr = \[ \];** **    arr**.push.**apply**(**arr,****bindT**("div")); **   arr**.push.**apply**(**arr,****bindT**("p")); console.log(**arr**); ### **②****Object.prototype****基本成员介绍** **(****1****)****constructor** **(****2****)****hasOwnProperty****判断属性是否为自己提供** console.log(**obj****.hasProperty**(**“name**”));判断obj是否具有**name**属性 **(****3****)****propertyIsEnumerable****判断属性是否可以枚举** **(****4****)****isPrototypeOf****判断是否为原型对象** console.log(**fn**.prototype.**isPrototypeOf**(**obj**)) 判断**fn**.prototype是**obj**的原型吗 **(****5****)****toSting( ) , toLocaleString( ) , valueOf( )** ### **③****包装类型****基本类型数据本不应该包含方法调用** 基本类型数据,如**数字,字符串**在调用方法时,解释器先将基本类型数据转换成对应的**对象类型**,然后调用方法,执行方法后返回结果,同时**销毁**其转换的对象 ### **④****get****、****set****读写器** **语法糖:为方便开发而给出的语法结构**     var obj = (function () {         var**num**\= 123;         return {            **get****num**() {                 console.log("执行getter读写器");                 return**num**;             },            **set****num**(value) {                 console.log("执行setter读写器");                **num**\= value;                 return**num**;             }         }     })();     console.log(obj.**num**);     obj.**num**\= 456;     console.log(obj.**num**); ![](https://images2015.cnblogs.com/blog/1071151/201702/1071151-20170225004703398-157874348.png)