做用域链、闭包和原型链

Function:  匿名函数,做用域,做用域链和闭包html

函数的重载:  什么是:函数名相同,参数列表不一样.根据传入函数的参数的不一样,整形不一样的逻辑.  数组

什么时候用:若是一项任务,根据不一样的参数,不执行不用的逻辑.  浏览器

优势:减轻调用者的负担.  问题:js语法不知函数的重载.闭包

 解决办法:在函数中都有arguments的属性,专门用于接收传入函数的全部参数值的类数组对象.app

匿名函数:  什么是:在函数定义时,不给函数名,即不被任何变量引用.  函数

什么时候用:肯定函数只使用一次.  优势:节约内存.  this

如何用:1.自调()--定义完当即执行.;2回调()--定之后,传给其余函数使用;prototype

做用域:  什么是:变量的有效范围.htm

 函数的生命周期(四个部分):对象

   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

相关文章
相关标签/搜索