博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
自学Javascript笔记
阅读量:6955 次
发布时间:2019-06-27

本文共 13250 字,大约阅读时间需要 44 分钟。

难点

Function.prototype.bind.apply(Date, [Date].concat(Array.prototype.slice.call(arguments)))= Date(arguments)function.toString()  //返回函数内容复制代码
/* [] --> "", {} --> "[object object]" 字符串+字符串,拼接得 */[] + {} // "[object object]""/* {}被识别为代码块, 剩下+[] --> +"" --> 0 */{} + [] //0复制代码
  1. 判断类型:
typeof //判断基本类型Object.prototype.toString.call() //判断对象类型复制代码
  1. 字符串剪切
slice(start,end)  //返回不包括end的新字符串substring(start,end)  //包括end的新字符串substr(start,length)  //返回start开始length长度新字符串复制代码

技巧

防抖:

let timer = null;function throttle(fn,delay,...args){  _self = this;  return function(){    if(timer) clearTimeout(timer);    timer = setTimeout(function(){      fn.apply(_self,args);    },delay);  }}复制代码

节流: 方式一:

let isExcute = true;function throttle(fn,delay,...args){  let _self = this;  if(isExcute === true)     return function(){      isExcute = false;      timer = setTimeout(        () => {          isExcute = true;          fn.apply(_self,args);        },delay);    }}复制代码

方式二:

let timeCache = 0;function throttle(fn,delay,...args){  let _self = this;  let time = Date.now();  if(time - timeCache > delay)     return function(){      timeCache = time;      setTimeout(() => {          fn.apply(_self,args);        },delay);    }}复制代码

类型转换

  1. 显式强制类型转换
  • Number() --> number
  • Boolean(): (null, undefined, false, "", NaN, +0、-0) -->false
    其他为true。
  • !!val --> boolean, +val --> number, val+"" --> string
  1. 隐式强制类型转换
    1. if, while, for,会隐式强制转换
      1. == 比较
      • 2.1 boolean与其它基本类型比较,会转换成数字,即 true --> 1, 'false' --> 0
      • 2.2 string与数字比较,会转换成数字。
      • 2.3 对象(包括包装对象)先用valueOf转换成基本类型值,如果没有valueOftoString返回的值再与其他 基本类型的值比较,如果都没有则返回TypeError
  1. 全局isNaN()遇到非数字和NaN都会返回false, 所以该用Number.isNaN()方法

编译阶段确定作用域

词法作用域

无论函数在哪里被调用,也无论它如何被调用,它的词法作用域都只由函数被声明时所处的位置所决定。

var a=4;function baz(){  console.log(a);}(function foo() {  var a=2;  function bar(){    console.log(a);  }    console.log(a); //2  bar(); //2  baz(); //4})();复制代码

执行上下文

函数被调用时便会创建执行上下文,创建执行上下文分为两个阶段:

一、创建阶段

执行上下文会分别创建变量对象,建立作用域链,以及确定this的指向。

graph LR当前执行上下文-->变量对象VO当前执行上下文-->作用域链ScopeChain(非包含关系)当前执行上下文-->this复制代码

创建变量对象流程

  1. 建立arguments对象。检查当前上下文中的参数,建立该对象下的属性与属性值。
  2. 检查当前上下文的函数声明,也就是使用function关键字声明的函数。在变量对象中以函数名建立一个属性,属性值为指向该函数所在内存地址的引用。如果函数名的属性已经存在,那么该属性将会被新的引用所覆盖。
  3. 检查当前上下文中的变量声明,每找到一个变量声明,就在变量对象中以变量名建立一个属性,属性值为undefined。如果该变量名的属性已经存在,为了防止同名的函数被修改为undefined,则会直接跳过,原属性值不会被修改。

变量提升

  1. function 的「创建」「初始化」和「赋值」都被提升了。
  2. var 的「创建」和「初始化」都被提升了。
  3. let 的「创建」过程被提升了,但是「初始化」没有提升。
  4. const 只有「创建」和「初始化」,没有「赋值」过程。
  • var
function test() {  console.log(a); //undefined  var a = 1;}复制代码

var a 创建并初始化成undefined,遇到var a = 1赋值为1

  • let, const
(function(){  console.log(a);  let a = 2;  // ReferenceError: a is undefined  const b = 3;})();复制代码

let a创建但未初始化,所以有临时性死区,直到let a = 2语句才初始化为undefined且赋值为2 const b创建且初始化成3,但没赋值

创建作用域链

根据该函数所引用的变量,如果在该作用域找不到引用变量,便会到上层作用域查找,由此建立起作用域链。

闭包

闭包指一个封闭作用域(()通常为一个函数),能在外部通过它的内部函数访问该作用域的变量。闭包只在访问

确定this指向

var a = 20;var obj = {    a: 10,    c: this.a + 20,    fn: function () {        return this.a;    }}var fn=obj.fn;console.log(obj.c); //40console.log(obj.fn());  //10console.log(fn());  //20 引用同一函数,但单独引用指向window或undefined复制代码

二、执行阶段

创建完成之后,就会开始执行代码,这个时候,会完成变量赋值,函数引用,以及执行其他代码。

函数调用栈Call Stack

function greeting() {   // [1] Some codes here   sayHi();   // [2] Some codes here}function sayHi() {   return "Hi!";}// Invoke the `greeting` functiongreeting();复制代码
  1. 遇到greeting();,便会将函数greeting推入Call Stack栈顶,执行greeting函数内的代码。
  2. 直到遇到sayHi();,便会将sayHi推入栈,执行sayHi函数内的代码,执行完毕后便将sayHi推出栈,继续执行greeting剩余的代码。
  3. 执行完毕后将greeting推出栈。

事件循环 Event Loop

task queue将函数推入Call Stack,函数执行时遇到异步的推进job queue,等Call Stack清空了,再将job queue依次推入Call Stack。则完成一轮循环。

语句:

continue和break

foo:for(var i=0;i<5;i++){  for(var j=0;j>i;j++) {    if (/*...*/) break foo; //跳出foo循环    else continue; //没标签,继续该循环的下一轮循环  }    if (/*...*/) break foo;   else continue foo;}复制代码

continue执行标记所在循环的下一轮循环。

break跳出标记所在循环。

原型和继承

graph LR[继承]-->A[不使用Object create]A-->[原型链继承]-->|组合为|E[组合继承]A-->[构造函数继承]C-->|组合为|E[组合继承]D-->|组合为|EE-->F[寄生组合继承]继承-->B[使用Object create]复制代码

new运算符流程

  1. 创建一个新对象,新对象的[[prototype]](或__proto__)指针指向构造函数的prototype(constructor属性在构造函数的prototype上)
  2. 将构造函数的作用域赋给新对象(this绑定到新对象)
  3. 执行构造函数代码(为新对象添加属性)
  4. 返回新对象

原型链继承

function SuperFunc(){
/*...*/}function SubFunc(){
/*...*/}SubFunc.prototype = new SuperFunc();SubFunc.prototype.constructor = SubFunc;var instance = new SubFunc();复制代码

优点:引用的方法能够复用 缺点:不能传递参数

构造函数继承

function SuperFunc(){
/*...*/}function SubFunc(){SuperFunc.call(this)}var instance = new SubFunc();复制代码

优点:父类引用属性不会共享,能传递参数 缺点:父类方法不能复用

组合继承

function SuperFunc(){
/*...*/}Super.prototype.method = function(){
/*...*/};function SubFunc(){SuperFunc.call(this)}SubFunc.prototype=new SuperFunc();SubFunc.prototype.method = function(){
/*...*/};var instance = new SubFunc();复制代码

优点:父类方法能够共享复用,引用属性不会共享 缺点:调用了两次SuperFunc构造函数,造成多余性能消耗

原型式继承

基于一个已有对象创建新对象

function cloneObj(obj){  function Func{}  Func.prototype = obj;  return new Func();}var clone = cloneObj(proto);  /*clone.__proto__ == Func.prototype == proto */Object.create(obj, prop) /* 可加prop*/复制代码

寄生式继承

在原型继承基础增加属性或方法

function inherit(obj){  var clone = cloneObj(obj);  clone.method = function(){};  return clone;}var clone = inherit(prototype);复制代码

寄生组合继承

function cloneObj(obj){  function Func{}  Func.prototype = obj;  return new Func();}function inherit(SubFunc,SuperFunc){  var prototype = cloneObj(SuperFunc.prototype);  /*prototype.__proto__ == SuperFunc.prototype*/  prototype.constructor = SubFunc;    SubFunc.prototype = prototype;  /* SubFunc.prototype.__proto__==SuperFunc.prototype */}function SuperFunc(){  this.prop = something;}SuperFunc.prototype.method = function(){};function SubFunc(){  SuperFunc.call(this);  this.anotherProp = something;}inherit(SubFunc,SuperFunc);SubFunc.prototype.anotherMethod = function(){};var instance = new SubFunc();复制代码

与原型链相关API总结

- prototypeObj.isPrototypeOf(obj); //调用对象是否在obj原型链上- obj instanceof constructor;  //constructor.prototype是否存在调用对象的原型链上- Object.getPrototypeOf(obj);  //返回obj对象的[[prototype]](或__proto__)属性。ES6中,如果obj不是对象,则强制转为对象。- Object.setPrototypeOf(obj, thePrototype);  //设置obj的[[prototype]](或__proto__)属性为thePrototype- obj.hasOwnProperty(prop);  //如果prop为自身属性,返回true- in //包含原型链上的字符串属性或symbol属性,则返回true复制代码

DOM相关:

DOM对象继承链: EventTarget --> Node --> document/Element/Attribute/...

html/body/frame api:

window.document  //返回对当前窗体所引用的document的引用window.frameElement  //返回嵌入的窗体比如

node

node属性

node.childNodes //包含全部子元素的数组(包含空字符文本节点和没标签括起来的文本节点)node.children //只包含标签节点/*以上返回即时更新的nodelist对象 (可能需要缓存)。*/node.firstchild = node.childNodes[0]node.lastchildnode.parentNodenode.previousSiblingnode.nextSiblingnode.nodeType  //节点属性类型 1.元素节点2.属性节点3.文本节点node.nodeName  //如果是元素节点则nodeName==tagName复制代码

node方法

parentNode.appendChild(childNode); return childNode  //在父元素末尾插入子元素parentNode.removeChild(childNode); return childNodeparentNode.replaceChild(newChild,oldChild); //new取代oldparentNode.contains(childNode); return boolean//parentNode是否包含childNodeparentNode.insertBefore(insertEl,targetEl); return insertEl//在目标元素前面插入要插入的元素复制代码

document

document方法

document.getElementsByTagName(tagName);document.getElementsByClassName(className);document.getElementsByName(name); //name属性document.getElementById(id);document.querySelectorAll(selector)  //返回non-live的nodelistdocument.querySelector(selector)document.createElement(tagName); //创建元素节点,比如divdocument.createTextNode(textValue); //创建文本节点复制代码

element

element属性

element.idelement.tagNameelement.className  //空格隔开的类名element.innerHTML //元素内部内容element.outerHTML //包含元素本身的内容  element.textContent  //元素内所有节点及子节点的文本内容(无论有无标签)复制代码

element方法

element.hasAttribute('attr');  return booleanelement.getAttribute('attr');  return string:value of attrelement.setAttribute('attr','value');element.removeAttribute('attr','value');复制代码

CSS/样式相关:

获取样式

element.style.styleName  //内联样式,style属性设置的css属性,驼峰样式window.getComputedStyle(element[,null或者伪类])  //实时改变。权威指南P432复制代码

元素边长/高/宽:

/*以下都是返回long int num类型*/element.clientLeft/Top  //元素左/上border大小element.scrollLeft/Top  //出现滚动条时,左/上方向已滚动的像素,否则为0element.offsetWidth  //元素可视区域padding+width+borderelement.clientWidth  //元素可视区域padding+widthelement.scrollWidth  //元素实际大小padding+width/*以下返回double float num类型*/element.getBoundingClientRect().width  //实际渲染可视的宽度(content+padding)复制代码

事件对象相对位置

MouseEvent.clientX //相对窗口的x坐标  MouseEvent.offsetX //事件对象与目标节点的内padding的x偏移量  MouseEvent.pageX //相对文档页面x边缘的偏移量MouseEvent.screenX //相对屏幕x边缘的偏移量复制代码

事件相关

dataTransfer

event.dataTransfer.effectAllowed = type;  //none、copy、move、link、linkMove、copyLink、copyMove、all默认为all,设置在源对象dragstart事件上,其他事件无效,dragenter和dragover的值将等于dragstart的值event.dataTransfer.dropEffect = type;  //none、copy、move、link目标对象的操作,可定义在drop,dragenter,dragover事件上复制代码
  1. 如果effectAllowed属性是定为none,则不允许拖放元素。
  2. 如果dropEffect属性设定为none,则不允许被拖放到目标元素中。
  3. 如果effectAllowed属性设定为all 或不设定,则dropEffect属性允许被设定为任何值。并且按指定的效果显示。
  4. 如果effectAllowed属性设定为具体的效果,dropEffect属性也设定了具体视觉效果,则两个具体效果之必须完全相等,否则不允许将被拖放元素拖放到目标元素中。

IO:

XMLHttpRequest(ajax):

//创建XHR对象var xhr=new XMLHttpRequest();//发送请求xhr.open("get"/"post",URL[,false/true]); //true异步xhr.responseType = type; //""(默认,字符串)、"ArrayBuffer"、"blob"、"document""json"、"text"(字符串)xhr.withCredentials = true;  //跨源时true为可以发送凭据(cookie、HTTP认证及客户端SSL证明等)xhr.send([request data]);//接收回应/*  responseText 响应文本  responseXML 响应XML DOM文档  status 响应HTTP状态  statusText 响应HTTP状态内容  readyState 请求/响应过程的当前活动阶段:  (0:未调用open   1:已调用open,未send   2:已send,未收到回应   3:开始接收回应   4:完成接受回应)*///服务器回应成功xhr.onreadystatechange = function(){    if(xhr.readyState == 4 && xhr.status == 200){        console.log(xhr.responseText);    } else{        console.log("no response!!");    }}//收到回应前取消异步请求xhr.abort();复制代码

xhr.withCredentials = true时,服务端的Access-allow-control-origin不能设置为'*'

FormData

可通过xhr.send()异步发送二进制文件

var data = new FormData([formElement]);data.append(DOMString name,DOMString/Blob/File value[,filename]); //插入键值对,value可为DOM String、Blob或File对象(File继承于Blob)复制代码

FileReader

可异步读取指定的blobFiles对象

var reader = new FileReader();复制代码

属性

error:读取时的异常

onload:完成
readystate:

常量名  |值|       描述EMPTY   |0|  还没有加载任何数据.LOADING |1|  数据正在被加载.DONE    |2|  已完成全部的读取请求.复制代码

result:操作完成时的文件内容

方法

readyAsArrayBuffer(blob):启动读取,result包含ArrayBuffer对象

readyAsDataURL(blob):启动读取,result包含DataURL(Base64编码)字符串
readyAsText(blob[, encoding /*编码方式*/ ]):启动读取,根据特殊的编码方式转化为字符串

SSE(服务器发送):

var source = new EventSource("URL");source.onmessage=function(){   //data的数据后有空行才触发onmessage    var data=event.data;}source.close(); //断开连接不重新链接复制代码

WebSockets:

var sockets= new WebSocket("URL" /* ws://或者'wss:// */); //绝对URLsocket.send("str")//只能发送纯文本//接收消息socket.onmessage=function(event){    vara data=event.data;}//另外3个事件open:成功链接触发error:错误。通信不能持续 //event额外有三个属性wasClean,code状态码,reason服务器信息close 连接关闭时触发复制代码

Web Worker

页面里:

var worker=new Worker("xx.js");//发送数据worker.postMessage("data"); //可传递任何对象数据);//错误worker.onerror = function(err){     err.filename  //错误文件名    ,err.lineno  //错误行号    ,err.message  //完整错误信息}//接收Worker发来数据复制代码
worker.onmessage=function(){    var data=event.data;};//停止工作worker.terminate();复制代码

Worker里

//接收数据self.onmessage=function(){    var data=event.data;};//发数据到页面self.postMessage();self.close(); //Worker内部停止工作,跟terminate一样。复制代码

Canvas

绘制

var canvas = canvasElement.getContext("2d"); //生成画布canvas.fillStyle=""; //填充样式canvas.fillRect(dx,dy,width,height); //填充矩形canvas.strokeRect(dx,dy,dWidth,dhHeight); //描边矩形canvas.drawImage(image,dx,dy);  //源图片canvas.drawImage(image,dx,dy,dWidth,dHeight);canvas.drawImage(image,sx,sy,sWidth,sHeight,dx,dy,dWidth,dHeight);复制代码
  • image:

绘制到上下文的元素。允许任何的canvas图像源(CanvasImageSource),例如:HTMLImageElementHTMLVideoElementHTMLCanvasElement

var image = new Image();imgae.src='...';复制代码
  • dx: 目标画布在目标canvas上X轴的位置。
  • dy: 目标画布在目标canvas上Y轴的位置。
  • dwidth: 在目标画布上绘制图像的宽度
  • dheight: 在目标画布上绘制图像的高度
  • sx: 源图像矩形选择框的左上角x坐标
  • sy: 源图像矩形选择框的左上角y坐标
  • sWidth: 源图像选择框宽度
  • sHeight: 源图像选择框高度

转换

var canvas = canvasElement.getContext("2d"); //生成画布canvas.toBlob(callback(blob/*转换的blob对象*/)[, type/*图片格式,如image/png*/][,encoderOptions/*图片格式为image/jpg、image/webp时指定图片质量,值为0-1*/]);canvas.toDataURL([type][, encoderOptions]);  //返回包含dataURI的DOMString复制代码

正则

  1. reg.prototype.exec()
  • 如果匹配到则始终返回第一个匹配到的文本,如果有括号匹配的则放在后面,否则返回null
  • 如果reg对象是全局查找(/g),则每次迭代exec都会另reg的lastIndex属性更新。
var reg1 = /abc/;var reg2 = /abc/g;var reg3 = /a(bc)/;var reg4 = /a(b)(c)/;var reg5 = /a(bc)/g;var str = "3abc4,5abc6";console.log(reg.exec(str));console.log(reg2.exec(str));console.log(reg3.exec(str));console.log(reg4.exec(str));console.log(reg5.exec(str));["abc", index: 1, input: "3abc4,5abc6", groups: undefined]["abc", index: 1, input: "3abc4,5abc6", groups: undefined]["abc", "bc", index: 1, input: "3abc4,5abc6", groups: undefined]["abc", "b","c", index: 1, input: "3abc4,5abc6", groups: undefined]["abc", "bc", index: 1, input: "3abc4,5abc6", groups: undefined]复制代码

2.str.prototype.match()

不是全局则跟exec一样,全局则返回所有匹配到的文本

var reg = /abc/;var reg2 = /abc/g;var reg3 = /a(bc)/;var reg4 = /a(bc)/g;var str = "3abc4,5abc6";console.log(str.match(reg));console.log(str.match(reg2));console.log(str.match(reg3));console.log(str.match(reg4));VM180:6 ["abc", index: 1, input: "3abc4,5abc6", groups: undefined]VM180:7 (2) ["abc", "abc"]VM180:8 (2) ["abc", "bc", index: 1, input: "3abc4,5abc6", groups: undefined]VM180:9 (2) ["abc", "abc"]复制代码

转载于:https://juejin.im/post/5b9b55016fb9a05d0d285c5e

你可能感兴趣的文章
分块下载文件的思路
查看>>
linux黄金命令[积累中]
查看>>
后渗透阶段
查看>>
***书单
查看>>
第五章
查看>>
hdu 2004
查看>>
气候变化脆弱性概念及评价方法研究
查看>>
html基础
查看>>
实验一201521460014
查看>>
控件添加序号
查看>>
Linux命令(1):cd命令
查看>>
SQLite查询记录总数
查看>>
java ee 8
查看>>
C# - 时间格式
查看>>
最终增强
查看>>
Mac下安装WebStrom
查看>>
【解决】Ubuntu命令行弹出光驱的方法
查看>>
68. Text Justification
查看>>
[转]详解SQL Server中SCAN和SEEK的区别
查看>>
C#预处理指令
查看>>