11/27/2016 10:42:12 PM
复习
- 面向对象编程的案例
- 面向对象编程的优势:可以避免全局变量污染,使代码结构更加清晰,便于维护
- 创建对象的方式
- 字面量 内置构造函数 自定义构造函数
- 构造函数
- 原型
- 对象的原型就是在创建对象的时候,构造函数的原型对象
- 继承
- 混入式继承(for-in)
- 原型继承
- 使用混入的方式为原型对象添加成员
-
代码
for(var k in parent){ Child.prototype[k] = parent[k]; }
- 直接替换原型对象
- Child.prototype = parent;
- constructor
- 原型对象中的属性,指向跟原型相关的构造函数
- 当构造函数没有参数的时候,创建对象时后面的小括号可以省略
-
代码
var p1 = new Person; console.log(p1);
-
- 原型链
- 对象都有原型,原型对象也是对象,
- 所以原型对象也有原型对象,
- 这样就形成一个连式结构,叫做原型链
- instanceof
- Object.prototype
- constructor
- hasOwnProperty(“属性名”)
- isPrototypeOf(对象)
- PropertyIsEnumerable()
- toString toLocaleString
- valueOf
- proto
经典继承
- Object.create()
- 创建出来一个obj对象,原型对象为obj1
- 这是ECMA5中新增的,会存在兼容性问题
- 经典继承的兼容性处理
- 1.浏览器能力检测
- 如果浏览器支持这个方法,就直接使用
- 如果浏览器不支持,
-
代码封装
//第一种: 这样会出现对全局的设置...管理混乱 Object.prototype.create = function () {} 要实现原型继承,就得找到原型,找原型的方式有两种 1.构造函数去找 所以要用构造函数,所以首先需要创建一个构造函数 function F(){} F.prototype = obj1; var obj = new F(); 2.对象去找 对象去找有兼容性问题,所以不用它 自己实现 创建一个对象继承自另外一个对象(原型继承,新的对象的原型需要变成obj1) var obj = {}; obj.__proto__ = obj1;
- 封装的自己实现原型继承的函数
- 参数:需要继承的对象(父对象)
- 返回值:新创建的对象(子对象)
-
完整分析代码
<script> var parentObj = { name :'waxun', age : 11, sayHi : function(){ console.log('-----'); } }; //将parentObj的地址复制了一份给childObj1 var childObj1 = parentObj; //将parentObj的内容作为childObj2的原型给了其子元素 //这种方法存在兼容性问题: ecma6 解决办法 var childObj2 = Object.create(parentObj); /* 3.isPrototypeOf 方法 * 对象名.isPrototypeOf(对象1) * 功能:判断对象是不是对象1的原型对象 * */ console.log(parentObj.isPrototypeOf(childObj2));//true /* * 解决Object.create()的兼容性问题 * 1. 能力检测 * * */ /*if(Object.create){ //如果支持的话,就将父级作为子集的原型存在 var childObj3 = Object.create(parentObj); }else{ //如果不支持 //第一种方法: // 直接将父级对象给自己对象的__proto__,但是__proto__又存在兼容性问题,不合适 // 这里是一个是一个普通的对象,所以不好通过prototype进行设置,可以,但是给了全局 // 第二种方法: // 需要一个构造函数来产生一个实例,就是子元素 // 这个构造函数的原型是父级的对象,new 出来的子元素就也有 //var childObj3.__proto__ = parentObj; function Fn(){}; Fn.prototype = parentObj; var childObj3 = new Fn(); }*/ function myCreate(parent){ if(Object.create){ return Object.create(parent); }else{ function Fn(){}; Fn.prototype = parent; return (new Fn()); } } var childObj4 = myCreate(parentObj); </script>
静态方法和实例方法
- 静态方法
- 通过构造函数去访问的方法就是静态方法
- 实例方法
- 通过实例去访问的方法就是实例方法
-
代码
function Person(){ this.sayHi = function(){ console.log('hi----'); } }; Person.sayHe = function () { console.log('sayHe'); }; Person.sayHe();//sayHe var p = new Person();//hi---- p.sayHi();
Function
- 创建函数的方式
-
- 函数声明
- 函数表达式
- new Function()
-
- Function
- 使用 new Function() 创建空函数
- 使用 new Function(methodBody) 创建一个具有函数体的函数
- 使用new Function(arg1,arg2,arg3,arg4,arg5….MethodBody) 创建一个具有参数和函数体的函数
- agr1…argn为 函数的形参名 字符串类型
-
Function代码案例
//1.使用 new Function() 创建空函数 var func = new Function(); func(); // 2.使用 new Function(methodBody) 创建一个具有函数体的函数 var func2 = new Function('console.log("hihi")'); func2();//hihi //3.使用new Function(arg1,arg2,arg3,arg4,arg5....MethodBody) 创建一个具有参数和函数体的函数 //求两个数的和 var fun3 = new Function('num1','num2','return num1+num2'); console.log(fun3(1, 2));//3
- Function 创建函数的
- 能够将字符串转换成代码!!!
- 如何处理方法体代码过长的问题
- 字符串拼接
- 模板—比较好用
- 反引号
-
代码
<script type="text/html" id="tpl"> var sum = 0; for(var i = n;i < m;i++){ if(i%2 == 0){ sum+=i; } } return sum; </script> //通过模板进行获取字符串 var tpl = document.getElementById('tpl'); var str = tpl.innerHTML; //console.log(str); var fn = new Function('n','m',str); console.log(fn(1, 100));
eval
- eval可以将字符串转换成代码,并且立即执行
-
代码
eval("var a = 10;"); console.log(a);
- Function 和 eval 区别
- Function是用来创建函数的,虽然也可以将字符串转换成代码,但需要掉用函数才能执行
- 会直接将字符串转换成代码并执行!!
- 都存在
- 效率问题
- 安全性问题
- 例子: 计算器
- res.innerText = eval(num1 + operator + num2);
Function和Object的关系
-
代码
//Function---->Function.prototype---->Object.prototype----->null console.log(Function instanceof Object); console.log(Function instanceof Function); //Object---->Function.prototype---->Object.prototype----->null console.log(Object instanceof Object); console.log(Object instanceof Function);
arguments
- 在定义函数的时候,如果有写形参,在调用的时候,实参的个数,可以和形参个数不对应
- arguments 伪数组
- 在函数内部的一个对象
- 在函数调用的时候,会将所有传入的实参,依次存入该对象
- 在实参个数不确定的情况下,就可以使用arguments对象来获取传入的实参
- 不论有没有形参,在函数调用的时候,都会将传入的实参存入arguments对象
-
代码案例
function test(){ for(var i = 0 ;i<arguments.length;i++){ console.log(arguments[i]); } } test(); test(1,2,3);//打印1 2 3
- arguments对象的
- length属性可以用来表示 用户传入的实参的个数
- callee:
- 指向当前arguments对象所在的函数
- 在匿名函数中实现递归
-
代码
function test(){ console.log(arguments.length);//0 实参的长度 console.log(arguments.callee);//指向当前arguments对象所在的函数,打印当前的函数的声明了 } test(); //在匿名函数中实现递归 (function(){ //因为会找函数自身 arguments.callee(); })();
函数的属性
- name是函数的函数名
- length属性是函数的形参的个数
- caller 指的就是函数的调用环境,
- 如果是全局的调用,caller就是null,
- 如果在其他的函数中,那这个caller就是外层的函数
-
代码
function test1(a,c,d){ console.log(test1.caller); } //test1();//null function test2(){ test1(); } test2();//现在打印的是test2的函数的声明,符合外层的定义 console.log(test1.length);//3*/ /*这样去找父级是谁就方便了*/ function Person(){} var p = new Person(); //去找出p对象的构造函数,就是其父级是谁 console.log(p.constructor.name);//Person console.log(p.__proto__.constructor.name);//Person
11/28/2016 1:27:00 AM