标签:
Function: 匿名函数,作用域,作用域链和闭包
函数的重载: 什么是:函数名相同,参数列表不同.根据传入函数的参数的不同,整形不同的逻辑.
何时用:如果一项任务,根据不同的参数,不执行不用的逻辑.
优点:减轻调用者的负担. 问题:js语法不知函数的重载.
解决办法:在函数中都有arguments的属性,专门用于接收传入函数的所有参数值的类数组对象.
匿名函数: 什么是:在函数定义时,不给函数名,即不被任何变量引用.
何时用:确定函数只使用一次. 优点:节约内存.
如何用:1.自调()--定义完立即执行.;2回调()--定以后,传给其他函数使用;
作用域: 什么是:变量的有效范围.
函数的生命周期(四个部分):
1.程序开始执行 执行环境栈-Execution Context Stack:专门按顺序保存每个函数的执行环境的集合. 全局EC:开始执行程序时,首先将全局EC压入ECS中. 创建window对象,保存所有全局函数和变量.window其实就是全局作用域.
2.函数声明时 创建函数对象,封装函数定义. 用函数名创建一个变量,引用函数对象. 在函数中添加scope属性,用来引用函数来自的作用域对象.
3.函数调用时 创建活动对象:Active Object.专门用来保存调用函数时的中局部变量. AO其实就是函数作用域对象; AO中的parent属性会引用函数来自的父级作用域对象.由此便形成了作用域链. 作用域链控制着变量的使用顺序,局部优先,然后是全局变量. 在再ECS中压入函数的执行环境.并且有属性scope chain 引用了AO
4.函数调用后 函数的执行环境弹栈,则AO伴随着引用消失而消失,则局部变量也跟着消失. 闭包 什么是:能保证局部变量的重用,又能保护其不受污染.
何时用:希望一个变量.......
怎么用:3步
1.使用外层函数将局部变量和内层函数包裹起来. 2.外层函数将内层函数对象返回. 3.调用外层函数获得返回的内层函数对象. 笔试时,一般先找出受保护的局部变量并计算出其最后的值.然后找到引用这个变量的函数.要注意函数只有被调用时,才会执行.
判断是否是自有属性:obj.hasOwnProperty("属性名");
回顾:面向对象 三大特点:
封装:将一个事物的属性和功能集中定义在一个对象中.
继承:父对象的成员,子对象无需创建,就可使用; 即重用了代码,又节省了内存.
多态-重写:同一种方法在不同的情况下表现出不同的状态.
1.创建对象--封装(3种方法--前两种用于创建单独的对象) var obj={属性名:属性值,...,方法名:function(){}}; var obj={};(new和()都能省略,但不能同时省略)obj[属性名]="属性值"; 定义构造函数;var obj=new 构造函数(属性值,...);
js底层,一切对象都是hash数组. 访问自己的属性:this.属性名;
new做了4件事
1.创建了一个空的对象;
2.设置新对象的_porto_属性继承构造函数的原型对象.
3.用新对象调用构造函数对象,将构造函数的this临时替换成新对象.
4.将生成的新对象的地址返回给变量. 2.调用对象的方法,操作对象的属性
原型对象:prototype 是集中保存父级对象的共有成员的对象.
如何获得:构造函数.prototype 子对象._proto_; 其中,子对象的_proto_属性是内部属性,无法直接获得. Object.getPrototypeOf(obj); 获取obj对象的父级原型对象. 判断自有属性和共有属性: 自有属性是指保存在子对象本地的成员,保存在父级原型对象中的是共有属性. obj.hasOwnPrototype("属性名");
判断obj是否包含自有属性.(false并不能表示这个属性就是共有属性,还可能是没有) 共有属性:在之前的基础上,obj.属性名!=undefined;此时表示为共有属性. 内置对象的API浏览器兼容性问题: 内置对象的API都存储在其原型对象中,如果不支持该方法就可以直接在其原型对象中添加该方法即可,重要的是该方法的实现原理. 判断继承关系: 根据原型对象判断: father.isPrototypeOf(child); 判断father是否是child的父级对象,同时也表示child是否是father的子对象. 根据构造函数判断: child instancof 构造函数 判断child是否是构造函数创造出来的对象.
笔试题:判断一个对象是否是数组类型,有几种方法.(4种)
1.Array.prototype.isPrototypeOf(xxx);//根据原型判断
2.xxx instanceof Array;//根据构造函数判断
3.根据对象的class属性判断. 其中,只有Object的直接子类对象可以直接调用xxx.toString();方法来获取class的值.其他的子类对象的toString()方法都被重写了.如何解决呢?--call
call强行调用函数,并且临时替换为this对象.(强行借用一个本无法调用到的函数.) Object.prototype.toString.call(obj)--返回"[object Array]" 所以在判断一个对象是否为数组时, 判断Object.prototype.toString.call(obj)==="[object Array]"
4.ES5以后支持Array.isArray(obj);--其底层所示用的原理还是使用的第三种方法. 作用域链和原型链: 作用域链是js默认执行的路线,同时也是控制变量的执行顺序. 而原型链则是控制js中对象的属性的执行循序.
面向对象中多个类型间如果有相同结构的属性和方法,则需要抽象到父类型中. 例如:都有name属性和fly方法.那么就可以抽象到父类中. 那么此时,在子类对象的创建过程中遇见问题. 首先是子类对象在创建时怎么调用父类的构造方法?(这里使有call和apply方法,作用都是强行调用一个函数.并将this改为当前正在创建的新对象.不同的是,call需要单独将参数写出,而apply只用使用arguments就可以,注意参数的前后顺序.) 然后是子类对象怎么获得父类对象的的方法?继承.通过方法 Object.setPrototypeOf(子类对象.prototype,父类对象.prototype);
修改继承: 修改继承只有3种方法
1.修改一个对象的父对象.--就是改变__proto__属性 child.__proto__=father=>Object.setPrototypeOf(child,father);
2.批量修改所有子对象的父对象--就是修改构造函数的prototype. 构造函数.prototype=father(强调必须在开始创建对象前修改)
3.两种类型间的继承 如果多个对象,拥有相同的属性结构和功能,那么就可以抽象出一个公共的父对象中
怎么做: 3.1 定义公共父类型,来集中定义共有的属性和功能.
3.2 让子类的原型对象继承父类的原型对象(目的是让子类可以使用父类中的共有方法)--inherits(继承):直接使用父对象中的成员--必须继承才能使用公共方法. Object.setPrototypeOf(子类型构造函数.prototype,父类型构造函数.prototype);
3.3 在子类构造函数中借用父类型构造函数--(extends)扩展:为子对象扩展父类没有的属性. 父类型构造函数.call(this,属性参数); 父类型构造函数.apply(this,arguments); call与apply的区别--同:都是强行调用一个函数,将this改为当前正在调用的对象 异:call每个参数必须独立传入,apply所有参数放在一个集合中集中传入(argument)
ES5新特性: 对象的属性:两大类-命名属性和内部属性(不可直接修改)
命名属性(自定义属性): 数据属性:实际存储属性值的属性(就是通常我们所写的.) 四大特性: value,wirtable,enumerable,configurable.(默认值都为true) 如何产看四大特性: Object.getOwnpropertyDescriptor(obj,"属性名") 如何设置四大特性: Object.defineProperty(obj,属性名,{//一次修改一个 特性:值,... }); Object.defineProperties(obj,{//一次修改多个. 属性名:{ 特性:值,... } }) 访问器属性(为了保护属性-通常需要定义的):--为了自定义保护的逻辑. 四大特性: get:function(){ return 受保护的属性值; } set:function(val){ //验证通过 受保护属性值=val; } enumerable,configurable. 何时使用:对一个属性自定义保护逻辑时. 如何使用:Object.defineProperty( obj,"属性名",{ get:function(){return 属性值},//js自动调用 set:function(val){//验证 赋值}//js自动调用 } ) 笔试题:在js中定义一个类型,包含共有属性和私有属性. js中的私有属性其实就是一个受闭包保护的一个局部变量.(注意,二者必须相互配合使用才能形成私有属性) ***注意:为一个已定义好的对象添加私有属性,使用添加外层函数的闭包结构(匿名函数的自调) 为多个子类对象添加相同的私有属性.则对构造函数设置一个受闭包保护的一个局部变量.(其中,构造函数就一个外部函数,所以不用再定义.)
防篡改:防止对已经创建好的对象的属性进行增减. 三个级别:
1.防扩展:禁止向对象中添加新属性\ 每个对象中都有一个extensible属性,控制能否向变量中添加新属性,默认为true. Object.preventExtension(obj);//设置对象中的extensible属性为false 问题,不妨删除.
2.密封:即防扩展,又防删除(是通过设置每个属性的configurable为false实现的). Object.seal(obj);
3.冻结:所有属性禁止增减,同时也禁止修改.
Object.freeze(obj); Object.create(): 何时:通过一个(父)对象创建一个子对象时使用. 笔试题:写一个函数,模拟create方法的实现过程
3步:1.基于现有父对象创建一个新的子对象;
2.继承父对象
3.同时扩展子对象的自有属性. --用Object,defineProperties(obj, 属性:{} );
注意: 原型方法/实例方法: 必须用具体对象才能调用 构造函数方法: 不需要任何具体对象即可直接调用
ES5-数组API 判断数组中所有元素,是否符合要求: every:判断每个元素是否都符合要求. arr.every(function(val,idx,arr){ //回调函数用于检测每个函数 //val;自动获得当前元素值 //idx:自动获得当前元素的位置 //arr:自动获得当前正在遍历的数组 }) some:判断是否包含满足要求的元素. 遍历: forEach:对原数组中的每个元素执行相同的操作. arr.forEach(function(val,idx,arr){ //对arr[idx]的值做出修改 }) map:将原数组中的每个元素加工后,生成新数组. arr.map(function(...){ //根据条件 return 新值; }) 过滤和汇总 filter:复制出原数组中符合要求的元素,组成新元素. var newarr=arr.filter(function(...){...}) reduce:将数组中每个元素的值汇总出一个结果.
bind:基于现有函数,创建一个新函数,提前永久绑定函数中的this为指定对象.
笔试题----模拟实现bind方法 call与apply与bind: call,apply:强行借用一个函数,并临时替换函数中的this为指定对象. call与apply是执行一个函数. bind:创建一个新函数,并永久绑定this和部分属性. bind不是执行函数,而是创建一个函数
将类数组对象转为纯数组: var new=[](或者Array.prototype).slice.call(arguments);
需要手写的函数:forEach,map,create,bind(请看下面的链接)
http://www.cnblogs.com/tianzun-blog/p/5966401.html
标签:
原文地址:http://www.cnblogs.com/tianzun-blog/p/5966428.html