zoukankan      html  css  js  c++  java
  • 【前端必备】三、JS篇

    1.运算符与隐式类型转换

    类型判断:

    typeof constructor.toString().indexOf()
    NaN是number
    Array、Date、Null都是Object
    function是function 未定义变量都是undefined
    "John".constructor // 返回函数 String()
    (3.14).constructor// 返回函数 Number() 
    false.constructor// 返回函数 Boolean()
    [1,2,3,4].constructor// 返回函数Array()
    {name:'John', age:34}.constructor  // 返回函数 Object() 
    new Date().constructor// 返回函数 Date()
    function () {}.constructor// 返回函数 Function()

    类型转换:

    • 对象转基本类型:
      先调用valueOf()再调用toString()
    • 其他简单类型-->String:
    方法 注意
    变量+""
    String(变量)
    变量.toString() ull和undefined这两个值没有toString()方法,
    Number.toString(2);将数字转成二进制
    ArrayObject.toString()会转为逗号分隔的列表内容
    • 其他数据类型-->Number:
    方法 注意
    Number(变量) true-->1 ; false-->0 ; null-->0 ;""或空格串-->0;
    undefined-->NaN;非纯数字串-->NaN;
    parseInt(变量,进制) 只保留开头数字,小数自动截断,非字符串会先自动转字符串。
    两个参数时做进制转换
    parseFloat(变量) 可以获得有效的小数部分
    • 转换为Boolean:
      0、-0、NaN、空串、null、undefined会转成false,其他都转成true
    • 伪数组转数组:
      Array.prototype.slice.call(arguments)

    隐式类型转换:

    算术运算符
    - * / +
    自动转换为Number
    任何值和NaN计算结果都是NaN
    任何的值和字符串做加法运算都会先转换为字符串,然后再做拼串操作
    如[1,2]+[2,3]="1,22,3" 'a'+ +'b'="aNaN"
    一元运算符
    typeof + - ++ --
    对一个其他的数据类型使用+ - ++ -- 会将其转换为数字
    逻辑运算符
    && || !
    能参与逻辑运算的都是布尔值
    非布尔值会先转换成布尔值
    关系运算符
    && || !
    *比较:非数值比较会先转换成数字
        两个字符串比较不会转换,而是比较它们的unicode编码
        任何值与NaN作比较都是false。(只有NaN自己不等于自己)
    *判等:==不同类型会转为相同类型(大部分时候转为数字)
        ===不会做类型转换

    调用非函数,或者读取null或者undefined的属性时,会报错 :

    isNaN("foo"); // true  
    isNaN(undefined); // true    
    isNaN({}); // true
    

    2.创建对象的方法

    1. new Object();
    2. 工厂函数(一个返回Object的函数)
    3. 构造函数,必须使用new来调用,this指向新建的对象。
      new 一个构造函数的执行流程
      (1)开辟内存空间,存储新创建的对象
      (2)链接到原型,
      (3)绑定this到新建对象,执行构造函数
      (4)将新建的对象作为返回值返回

    通过同一个构造函数实例化的多个对象具有相同的原型对象。
    实例对象有一个__proto__属性,指向该实例对象对应的原型对象
    实例.__proto__.constructor==构造函数 //true
    构造函数有prototype属性,实例有__proto__属性
    实例.__proto__==构造函数.prototype

    试着实现一下instanceof:

    function instanceof(left, right) {  
        // 获得类型的原型  
        let prototype = right.prototype  
        // 获得对象的原型  
        left = left.__proto__  
        // 判断对象的类型是否等于类型的原型  
        while (true) {  
        	if (left === null)  
        		return false  
        	if (prototype === left)  
        		return true  
        	left = left.__proto__  
        }  
    }
    

    3.闭包

    闭包是指有权访问另一函数作用域中的变量的函数。
    换句话说,在函数内定义一个嵌套的函数时,就构成了一个闭包, 它允许嵌套函数访问外层函数的变量。 通过返回嵌套函数,允许你维护对外部函数中局部变量、参数、和内函数声明的访问。
    这种封装允许你在外部作用域中隐藏和保护执行环境,并且暴露公共接口,进而通过公共接口执行进一步的操作。

    缺点:函数执行完后, 函数内的局部变量没有释放,占用内存时间会变长,容易造成内存泄露。
    解决:能不用闭包就不用,及时释放。(将引用置为null)
    经典面试题:
    循环中使用闭包解决 var 定义函数的问题:

    • 解决方法一,使用闭包:
      (包装了一层立即执行函数,这样就不会污染全局变量了)

    • 解决方法二,使用let:

    • 解决方法三,使用setTimeout的第三个参数:

    4.作用域和上下文

    作用域(Scope)和上下文(Context)
    作用域决定了代码区块中变量和其他资源的可见性。它指一个变量的作用范围。相对于上下文对象是静态的, 在编写代码时就确定了。

    上下文(context)是指 this 在同一作用域内的值,是代码的执行环境。
    执行上下文是动态的, 调用函数时创建, 函数调用结束时就会自动释放。
    有三种类型的ECMAScript代码:全局代码,函数代码和eval代码。代码执行在它的执行上下文里。有唯一的全局上下文,以及可能有多个函数和eval上下文。

    1.在全局代码执行前, JS引擎就会创建一个栈来存储管理所有的执行上下文对象
    2.在全局执行上下文(window)确定后, 将其添加到栈中(压栈)
    3.在函数执行上下文创建后, 将其添加到栈中(压栈)
    4.在当前函数执行完后,将栈顶的对象移除(出栈)
    5.当所有的代码执行完后, 栈中只剩下window

    5.内存溢出和内存泄漏

    内存溢出:一种程序运行出现的错误。当程序运行需要的内存超过了剩余的内存时, 就出抛出内存溢出的错误。
    内存泄漏:占用的内存没有及时释放。
    注意,内存泄露的次数积累多了,就容易导致内存溢出。
    常见的内存泄露:
    •意外的全局变量
    •没有及时清理的计时器或回调函数

    6.深浅拷贝

    将引用复制改为值复制:

    • Object.assign(target, ...sources)
      将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。 不会跳过那些值为 null 或 undefined 的源对象。
      只能解决第一层的问题
    • 展开运算符 let b = {...a}
      只能解决一层
    • JSON.parse(JSON.stringify(object))
      会忽略 undefined、symbol
      不能序列化函数
      不能解决循环引用(父子循环引用、兄弟循环引用)的对象
    /**
    * 对象克隆
    * 支持基本数据类型及对象
    * 递归方法
    */
    // 方法一:
    function clone(obj) {
    	var o;
    	switch (typeof obj) {
    		case "undefined":
    			break;
    		case "string":
    		o = obj + "";
    		break;
    		case "number":
    			o = obj - 0;
    			break;
    		case "boolean":
    			o = obj;
    			break;
    		case "object": // object 分为两种情况 对象(Object)或数组(Array)
    		if (obj === null) {
    			o = null;
    		} else {
    			if (Object.prototype.toString.call(obj).slice(8, -1) === "Array") {
    			o = [];
    			for (var i = 0; i < obj.length; i++) {
    				o.push(clone(obj[i]));
    				}
    			} else {
    			o = {};
    			for (var k in obj) {
    				o[k] = clone(obj[k]);
    				}
    			}
    		}
    			break;
    		default:
    		o = obj;
    		break;
    	}
    	return o;                                 
    } 
    

    7.异步与同步

      js 是单线程,而且有一个任务队列:全部的同步任务执行完毕后,再来执行异步任务。
      同步任务在主线程上排队执行,异步任务在任务队列等待,主线程上的同步任务执行完了,才会从任务队列取出异步任务执行。
    常见的异步操作:网络请求、定时任务、事件绑定、promise

    异步编程的4种方式:
    • 回调函数
    • 事件监听
    f1.on('done', f2);
    f1.trigger('done');
    
    • 发布/订阅
    jQuery.subscribe("done", f2);
    jQuery.publish("done");
    jQuery.unsubscribe("done", f2);
    
    • promise对象

    8.伪数组

    特性:具有length属性、按索引方式存储数据、不具有数组的push,pop等方法。
    例子:函数的arguments参数,调用getElementsByTagName,document.childNodes之类的返回的NodeList对象。
    将伪数组转为数组:

    function log(){ 
    	var args = Array.prototype.slice.call(arguments); 
    	//为了使用unshift数组方法,将argument转化为真正的数组 
    	args.unshift('(app)'); 
    	console.log.apply(console, args);
     };
    

    9.arguments的callee和caller属性

    两个属性都是指针
    arguments.callee指向当前函数,
    arguments.caller指向当前函数的父函数
    可用于递归函数中的自调用,实现函数执行与函数名的解耦合。

    10.this、call、apply、bind

    this 表示当前对象的一个引用
    • 在方法中,this 表示该方法所属的对象。
    • 如果单独使用,this 表示全局对象。
    • 在函数中,this 表示全局对象。
    • 在函数中,在严格模式下,this 是未定义的(undefined)。
    • 在事件中,this 表示接收事件的元素。
    类似 call() 和 apply() 方法可以将 this 引用到任何对象。

    call、apply是立即调用函数,apply的第二个参数是参数数组。

    persion1.say.call(p2, "实验小学", "六年级");  
    persion1.say.apply(p2, ["实验小学", "六年级"]); 
    

    将第一个参数p2作为say方法内this的指向,后面的参数作为say函数的参数。
    bind传参与call相同,但bind返回一个函数,要加()才能立即执行。
    persion1.say.bind(p2, "实验小学", "六年级")();

    11.事件机制

    事件触发的三个阶段 :

      路径:Window <——> Document <——> <html> <——> … <——> 事件触发处

    • 捕获阶段:遇到注册的捕获事件会触发
    • 目标阶段:传播到事件触发处时触发注册的事件
    • 冒泡阶段:遇到注册的冒泡事件会触发
      如果给一个目标节点同时注册冒泡和捕获事件,事件触发会按照注册的顺序执行。

    注册事件:

      属性注册:
      

    • <button onlick="sayHello()">点击</button>

      方法注册:

    • element.addEventListener(event, function, useCapture);
          //usecapture默认false冒泡,true捕获
    • element.attachEvent(event,function); //IE中
    • EventTarget.onEventName=function(e){};

    注销事件:

    • removeEventListener(event,function,capture/bubble); 
    • detachEvent(event,function); 
    • 事件属性赋值为null

    阻止事件冒泡:

    box3.onclick = function (event) {
    alert("child");
    //阻止冒泡
        event = event || window.event;
    if (event && event.stopPropagation) {
            event.stopPropagation();//w3c(火狐、谷歌、IE11)
        } else {
            event.cancelBubble = true;//IE10以下
        }
    }
    

    事件委托(事件代理):

    如果一个节点中的子节点是动态生成的,那么子节点需要注册事件的话应该委托给父节点
    优点:减少内存消耗,提高性能。

    12.BOM与DOM

    BOM与DOM的关系:

    系统对话框:

    alert();	//不同浏览器中的外观是不一样的
    confirm();  //兼容不好
    prompt();	//不推荐使用
    

    window操作窗口

      window.open(url,target,param)
      window.close()
      新窗口.moveTo(5,5)
      新窗口.resizeTo()
      window.resizeBy()

    location对象:

    window.location可以简写成location。location相当于浏览器地址栏,可以将url解析成独立的片段。

    • 属性
      • href:跳转
      • hash 返回url中#后面的内容,包含#
      • host 主机名,包括端口
      • hostname 主机名
      • pathname url中的路径部分
      • protocol 协议 一般是http、https
      • search 查询字符串
    • 方法
      • location.assign():改变浏览器地址栏的地址,并记录到历史中
        设置location.href 就会调用assign()。一般使用location.href 进行页面之间的跳转。
      • location.replace():替换浏览器地址栏的地址,不会记录到历史中
      • location.reload():重新加载

    window.navigator的一些属性 可以获取客户端的一些信息。
    appCodeName appName appVersion cookieEnabled platform userAgent systemLanguage

    history对象:

    window.history 包含用户(在浏览器窗口中)访问过的 URL。

    方法 描述
    back() 加载 history 列表中的前一个 URL
    forward() 加载 history 列表中的下一个 URL
    go() 加载 history 列表中的某个具体页面

    screen对象:

    Screen 对象包含有关客户端显示屏幕的信息。
    availHeight availWidth colorDepth height width pixelDepth

  • 相关阅读:
    ExtJs之Grid
    [java]转:String Date Calendar之间的转换
    SQL Server脚本备份
    Java实现文件夹的复制(包括子文件夹与文件)
    Android webview使用详解
    zxing条码扫描横屏修改
    Genymotion的安装与eclipse配置教程
    开发中遇到的问题
    sql中COUNT()+GROUP BY +HAVING的组合使用
    由于包名与引用的库名相同导致的报错
  • 原文地址:https://www.cnblogs.com/mthz/p/web3.html
Copyright © 2011-2022 走看看