04.js基本知识点总结

94 阅读5分钟
一.Objectd对象

对象有Array,String,RexExp,Date...等,对象具有属性和方法,都是预定义好的,js是基于原型的面向对象语言。 面向对象三大特点:封装,继承,多态

  1. 开发方式:一种是面向过程(开始-结束);另外一种是面向对象,对象(属性和方法),js中万物皆对象,一切对象的底层都是hash数组。面向对象:数据包含在一个事物之中。
  2. 封装自定义对象:3种
  • 直接量方式:

    var obj={"属性名""属性值",
             ....,
             "方法名"function(){操作},
             ...,}其中function可以简化为箭头函数
    
  1. 访问对象的属性和方法:obj.属性名;---obj.["属性名"];obj.方法名;---obj"方法名";点访问起来更简单。 如果访问到不存在的属性返回undefind;可以随时添加新属性和方法(obj.属性名=新值;obj.方法名=function(){}) ;因为对象的底层是hash数组。必须使用for in循环,obj[i],才能拿到对象所有的东西;如果在对象的方法里,使用对象自己的属性,要写为this.属性名。

  2. this的指向:单个元素绑定事件,this指的是这个元素;多个元素绑定事件this指的是当前元素;定时器中的this指的是window;箭头函数this指的是外部对象;函数中的this,谁在调用此方法this就是谁;构造函数之中this指的是当前正在创建的对象。

  3. 预定义构造函数的方式:

    var obj=new Object()//空对象,需要添加属性和方法
    obj.属性名=新值;
    obj.方法名=function(){};
    预定义构造函数和直接量方式一次只能创建一个对象。批量创建多个对象推荐使用自定义构造函数方式。
    
  4. 自定义构造函数方式:2步

     1.创建自定义构造函数
    function 类名(name,age,hobby){
    this.name=name;
    this.age=age;
    this.hobby=hobby;}这里面不能创建方法,否则每个对象都会创建一个方法,浪费内存。
    2.调用构造函数创建对象
    var obj=new 类名(实参,...);
    
  5. 面向对象的优点:逼格高所以属性和方法都保存在一个对象之中,更符合现实更有意义;每个功能特地分开写,便于以后维护;铁索连舟一个方法触发多个方法联动。前提是要搞清楚this的指向问题。

  6. 继承:父对象的属性和方法,子对象可以直接使用。继承的好处提高代码的复用性,节约了内存空间,提升了网站性能。

  7. 如何找到原型对象(父对象):保存了一类子对象共有属性和共有方法

     1.对象名.__proto__;//必须有对象才能找
     2.构造函数名.prototype;构造函数名
    
  8. 两链一包:作用域链,原型链和闭包。原型链:每个对象都有一个属性:proto,可以一层一层的找到每个人的父亲,形成链式结构。可以找到父对象的成员(属性和方法),作用:找到共有属性和共有方法。最顶层是Object的原型。有了原型对象,可以设置共有属性和共有方法【1.原型对象.属性名=属性值;2.原型对象。方法名=function(){}】

二.继承
  1. 判断是自有属性还是共有属性:

       判断自有:obj.hasOwnProperty("属性名") ;结果为true说明是自有属性,结果为false有两种可能,说明可能是共有属性也可能是没有这个属性。
       判断共有:if(obj.hasOwnProperty("属性名")==false&&"属性名"in obj){
       共有}else{没有}//里面的in 是关键字,会自动查找整条原型链上的属性,找到了结果为true找不到结果为false。
       完整公式:if(obj.hasOwnProperty("属性名")){自有}
       else{if("属性名"in obj){共有}
       else{没有}}
    
  2. 修改自有属性:obj.属性名=新属性值;删除自有属性:delete.obj.属性名。修改共有属性:原型对象.属性名=新属性值。删除共有属性:delete 原型对象.属性名。

  3. 如何为老IE的数组添加indexOf方法,或者说如何为一类人创建某个方法。

     if(Array.prototype.indexOf===undefined){判断是不是老IE
     Array.prototype.indexOf=function(key,starti){
     	starti===undefined&&(starti=0);
     	for(var i=starti;i<this.length;i++){
     	if(this[i]===key){
     			 return i;}
     			}
     			return -1;}}
     	var arr1=[1,2,3,4,5];
     	var arr2=[2,4,6,8,10];
                     length是传入的数组长度
    
  4. 如何判断x是不是一个数组:4种方法。typeOf()只能检查原始类型,如果检查引用类型会得到的结果都是一个object。

  • 判断x是否继承自Array.prototype:Array.prototype.isPrototypeOf(x);结果为true说明是数组,结果为false说明不是数组。
  • 判断x是不是由Array这个构造函数创建的:x instanceof Array;true说明是数组,反之不是数组;
  • Array.isArray(x):ES5新增数组判断方法,只有数组可以使用。
  • 输出 对象的字符串形式:在Object的原型上保存着最原始的toString方法。原始的toString输出形式:[object 构造函数名] 。
    • 多态:子对象觉得父对象的成员(属性和方法),不好用,就在本地定义了同名函数,覆盖了父对象的成员,不严格定义:同一个方法,不同人的使用,效果不同有多种形态。固定写法:Object.prototype.toString.call(x)==="[object Array]"
  1. 实现自定义继承:两个对象之间设置继承---子对象.——proto__=父对象

  2. 多个对象之间设置继承:构造函数名.prototype=父对象;要在开始创建对象之前就设置好继承关系。

  3. class关键字:简化面向对象(封装,继承,多态)

     class 类名 extends 老类{constructor(name,age,hobby,...){//放在constructor里面的都是自由属性
     super(name,age);
     this.hobby=hobby;
     }//放在constructor外面的都是共有方法
     }
    
  4. Function:闭包---- 作用域:1、全局:随处可用,可以反复使用,缺点:容易被污染2、函数:只能在函数调用时内部可用,不会被污染,缺点:一次性的,是会自动释放的。

  5. 函数的执行原理:

         1、程序加载时
     	创建执行环境栈(ECS):保存函数调用顺序的数组
     	首先压入全局执行环境(全局EC)
     	全局EC引用着全局对象window
     	window中保存着我们全局变量
    
         2、定义函数时
     	创建函数对象:封装代码段
     	在函数对象之中有一个scope(作用域)属性:记录着函数来自己的作用域是哪里
     	全局函数的scope都是window
    
         3、调用前
     	在执行环境栈(ECS)压入新的EC(函数的EC)
     	创建出活动对象(AO):保存着本次函数调用时用到的局部变量
     	在函数的EC中有一个scope chain(作用域链)属性引用着AO
     	AO有一个parent属性是函数的scope引用着的对象
    
         4、调用时:
     	正是因为有前面三步,才来带变量的使用规则:优先使用自己的,自己没有找全局,全局没有会报错
    
         5、调用完:
     	函数的EC会出栈,没人引用AO,AO自动释放,局部变量也就释放了
    
  6. 闭包:希望保护一个可以【反复使用的局部变量】的一种词法结构,其实还是一个函数,只是写法比较特殊:如何使用:1、两个函数进行嵌套2、外层函数创建出受保护的变3、外层函数return出内层函数4、内层函数再操作受保护的变量

  7. 强调:1、判断是不是闭包:有没有两个函数嵌套,返回了内层函数,内层函数再操作受保护的变量2、外层函数调用了几次,就创建了几个闭包,受保护的变量就有了几个副本3、同一次外层函数调用,返回的内层函数,都是在操作同一个受保护的变量;缺点:受保护的变量,永远都不会被释放,使用过多,会导致内存泄漏 - 不可多用

  8. 闭包何事使用:

    1、三个事件需要防抖节流 - 共同点:触发的速度飞快
    		1、elem.onmousemove - 鼠标移动事件
    		2input.oninput - 每次输入/改变都会触发
    		3、onresize - 每次窗口改变大小都会触发
    
    	防抖节流的公式:
    	function fdjl(){
    		var timer=null;
    		return function(){
    			if(timer!==null)   {clearTimeout(timer);timer=null;}
    			timer=setTimeout(()=>{
    				操作
    			},500)
    		}
    	}
    	
    	var inner=fdjl();
    
    	elem.on事件名=function(){
    		inner();
    	}
    

两链一包:1、作用域链:以函数的EC的scope chain属性为起点,经过AO,逐级引用,形成的一条链式结构,我们就称之为叫做作用域链作用:查找变量,带来了变量的使用规则:优先使用自己的,自己没有找全局,全局没有就报错;2、原型链:每个对象都有一个属性叫做.proto,可以一层一层的找到每个对象的原型对象,最顶层的就是Object的原型,形成的一条链式结构,我们就称之为叫做原型链;作用:查找对象的属性和方法,哪怕自己没有也会顺着原型链向上找,怪不得人人都能用toString(),因为他在最顶层3、闭包:希望保护一个可以【反复使用的局部变量】的一种词法结构,其实还是一个函数,只是写法比较特殊:作用:专门用于防抖节流