关于面向对象的基础总结,以及原型链和作用域链的学习方法总结!

封装的思想总结

变量

1.值类型

基本数据类型,一般为值类型。变量存在栈里面,这里直接拷贝数据赋值給变量。(因此另个变量 存着相同数据,改变其中一个不影响另 外一个。)

2.引用类型 

一般复杂数据类型的数据是存放在堆里面的,而变量接收的只是访问数据内存地址的引用(拷贝 一份赋给变量)。(因此指向相同引 用的变量,改变其中一个引用内存里的数据,另一个也会改 变。)

in运算符作用:

用于检测对象中时候有该属性(返回一个boolean值) 语法:   boolen "name" in Object

捕获异常:

try{}catch(err){}就是捕获异常,最大的作用就是如果觉得这有问题,对该语句,try..catch之后就可以继续执行后面的代 码。而throw,可以通过new throw("自定义错误")的 方法把错误抛出到外界.

函数创建的3种形式

1.声明式

function fn(){},这种形式为声明式,在函数创建开始就存在了。在上面调用和下面调用都可以.可以理解为申明了一个变量 ,之后再声明的同时瞬间给变量赋值了 一个指向函数的引用(可能不太准确)

2.函数的自变量形式

var fn = function(){},这种形式为声明式,调用它,只能在函数的下面调用。可以理解为申明了一个变量,之后执行到赋 值语句的时候才给变量赋值 了一个指向函数的引用

3.构造函数的形式

new function 其实所有的函数都可以当做构造函数来使用。但是一般new出来的东西我们都是通过this.属性.给新的对象 添加属性。下面对 varp = new person();(这里假设已经存在person这个函数)的步骤进行解析。
1.用new申请里一个一块内存空间
2.调用函数peroson,创建一个对象p.
3.通过peroson里的this.属性,给新的对象添加属性。This的指向指给p

new Function语法

var 函数名 = new Function( arg1, arg2, arg3, ..., argN, body );相当于直接把代码传入进入Function里面(前几个是传的 参数,后几个是传的return 的函数体)获取函数的类型 函数的类型其实就是获取函数的名字。1.可以通过fn.name的方法获得。

2.可以通过字符串的操作获得(通过replace先把function替换成|,之后通过查找|.indexof()获取索引,之后再通过)“)”.in dexof()获取索引,最后通过slice方法截取两个索引就得到了函数的名字。

3.通过正则的方法

(/function (.+)\).exec( s )[ 1 ]

继承 拿来主义(两种继承方式)

1.组合继承
o2.extend = function ( obj ) {
    for ( var k in obj ) {
      this[ k ] = obj[ k ] } 
  }   
   o2.extend( o1 );  // 继承
2.原型继承

第一种(动态添加)
Person.prototype.sayHello = function () { alert (' 哈哈哈 ');};
第二种(覆盖型)
Person.prototype = {
 
sayHello: function() {},
 
sayGoodbye: function() {},
 
sayLove: function () {}};
第三种(利用组合式继承 添加原型成员)
fn.prototype.extend = function (obj) {};   之后把要添加的方法通过obj的方式传入进去         

*原型链*

function Person(){};    var p1 = new Person(){};          var p2 = new Person(){};            的原型链结构  

1.记住以下的特点,对于实例来说,它只有一个__proto__属性,指向创建它的构造函数.prototype所指向的对象

2.对于构造函数来说,它有prototype属性,指向实例的原型,还有一个__proto__的属性指向function.prototype
3.对于原型来说他有两个属性,一个constructor指向构造函数,一个__proto__指向object.prototype

4.function比较特殊,它创建了自己而它的__proto__也指向function.prototype

5.在一定情况下我们可以理解为fn.prototype是object.prototype的一个实例,但是不准确

object.prototype成员

1.一堆带_ _的属性除了 __proto__ 其他可以不考虑
2.constructor 存的是构造函数的引用,可以理解为就是构造函数
3.hasOwnProperty有自己的属性, 检查属性是否是自己原生提供的, 如果是被继承的 则返回 false。p.hasOwnProperty( 'name' )
4.isPrototypeOf 判断 对象1 是否为 对象2 的原型对象。对象1.isPrototypeOf( 对象2 )
5.propertyIsEnumerable这个方法判断属性是否可以被枚举, 同时判断属性是否是自己提供的
6.toString, toLocaleString, valueOf toString把对象转换成字符,toLocaleString把对象转换我当地的字符(Date对象里用)valueOf把对象装换成数

运算符

instanceof 判断当前对象是否在其构造函数.prototype的原型链上

eval和new Function用法
eval eval( 'var a = 10;' )缺点会污染全局作用域
new function var b =(new Function( 'var a; return a = 10;' ))();比eval好用,不会污染全局作用域

静态方法和实例方法

静态方法 静态方法就是直接给构造函数绑定的方法。Fn.call = function(){}
实例方法 给原型上绑定的方法就做实例方法,因为构造函数创建出来的对象如果没有这种方法他就回到原型里去找这个方法。通常我们会让实例 方法里面return静态方法,这样就实现了静态方法控制实例方法的目的。不如Jquery里就是这么做的。
Goods.compare = function ( s1, s2 ) {return s1.name === s2.name &&s1.price === s2.price &&s1.img === s2.img;};Goods.prototype.isEqualsTo = fu nction ( o ) {return Go ods.compare( this, o ); }

函数相关属性成员

1.函数名.name 显示函数的名字
2.函数名.length 形参的数量
3.函数名.caller 获得调用函数的函数。也就是说,如果在函数里console.log(当前函数名.caller),就可以获得函数调用它的函数的函数名。
4.arguments.callee 一般用于匿名函数的自调用(有名字的也可以自调用)

递归

两点内容 第一点return解决问题的递归公式
第二点用if()添加递归的临界条件
递归的遍历原理 二叉树深度遍历

*作用域链*

块级作用域
所谓的块级作用域就是 用一个块结构分割变量的访问区域
词法作用域
就是变量的作用范围, 在书写代码的时候就已经决定, 与运行时无关。分割作用域的只有函数(也是js的主要作用域)

变量提升 浏览器预加载的时候会把函数名加上变量名做提升(名字相同函数名会覆盖变量名)
可以理解为函数提升是相当于给变量提升的同时直接给函数赋值一个函数(不准确)
变量搜索原则
在代码的运行过程中, 如果访问某一个变量,那么首先在当前链上找 ( 无序 ), 如果没有, 在 n-1 级上找( 在函数内部允许访问定义在函数外部的变量 ) ,如此往复, 直到 0 级链, 如果还没有 抛出异常如果找到, 则结束寻找, 直接获得该链上变量的数据

作用域链的原理图

原理口述:在浏览器进行预加载的时候就会把全局中的全局变量已经声明函数进行提升(函数内部会有一个global对象装的这些变量),我们可以 理解为这就是第0级链条里 的东西。之后呢,函数调用的时候,就会对函数内部的变量进行再提升(这时候就会生成一个新的对象,这个对象里面 装着局部变量里的内容),我们就可以理解为这是1级链的内容。之后如果函数里还有函数,那么依次下去,2.3.4级链递加下去...


作用域链和原型链的关系:

不同本质上他们是两个东西,原型链是属性搜索原则,而属性搜索必须依附于对象,也就是说你在搜索的时候要先找到对象再找属性而变量搜 索原则则是搜索的是变量,开始的时候变量会 提升,函数分割作用域链,产生不同级别的链,通过链条来访问变量
共同之处 我强加上去的,可以说他们可以通过对象能联系到一块,属性,依附于对象,而对象的引用存在变量里面。因此也可以把他们联系在 一起。

*闭包*:

1.常见的模式
function fn(name,age){
var a = name;
var b = age;
return {
"name":function name(){return a;},
"age":function(){return b;}}
};
通过返回一个对象,而对象里的属性分别接收的是函数,而在函数里面在return这个变量就实现了把name和age调出去
2.缓存功能的应用
var fib = (function () {
    var arr = [];
    return function ( n ) {
      // count++;
用于测试性能用的
     if ( n < 0 ) throw new Error( '数字不允许是负数' );
   var res = arr[ n ];   // 先到数组中取
     if ( res !== undefined ) {
      // 数组中有数据
      return res;
     } else {
      // 如果是 1 或 0 则将 1 返回给 res
      // 否则递归结果交给 res;
      if ( n === 0 || n === 1 ) {
       res =  1;
      } else {
       res = arguments.callee( n - 1 ) + 
          arguments.callee( n - 2 );
      }
      arr[ n ] = res;  // 将计算的结果放到数组中, 那么下一次再计算的
          // 时候可以直接拿来用, 就不用计算量
      return res;
      }
    };
   })();  
   fib( 5 );










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值