JavaScript

原型链

每创建一个函数,解析器都会想函数中添加一个prototype原型属性,这个prototype属性对应着一个对象,这个对象就是原型对象
如果该函数是普通函数调用,则prototype没作用
如果该函数是以构造函数调用,则创建的对象中都会有一个隐含的属性,指向该构造函数的原型对象,通过__prototype__来访问该属性
对象.hasOwnProperty(属性)        //对象自身中是否包含某种属性
原型对象也是对象,所以也有原型 object对象没有原型
对象要使用某个属性或方法,会现在自身寻找→原型对象中寻找→原型对象的原型中寻找……直到object对象原型

数组

会影响原数组的数组方法:push,pop,shift,unshift,reverse,splice,sort
      <script>
        let arr = [1,2,3,4,5]
          //返回截取从0到3组成的新数组
        console.log(arr.slice(0,3)); 
         //返回删除索引0开始的1个元素 并用22,33插入删除的位置
        console.log(arr.splice(0,1,'22','33'));  
      </script>
数组去重
 <script>
      let arr = [1, 2, 2, 2, 3, 4, 5, 2, 3, 1, 2, 0]
      for (let i = 0; i < arr.length; i++) {
        for (let j = i + 1; j < arr.length; j++) {
          if (arr[i] == arr[j]) {
            arr.splice(j, 1)
            j--
          }
        }
      }
      console.log(arr.sort())
    </script>

this的情况

一、隐式绑定 没有 对象.函数 指向window

–函数调用时前面并未指定任何对象,这种情况下this指向全局对象window。
function fn1() {
    let fn2 = function () {
        console.log(this); //window
        fn3();
    };
    console.log(this); //window
    fn2();
};

function fn3() {
    console.log(this); //window
};

fn1();
–如果函数调用时,前面存在调用它的对象,那么this就会隐式绑定到这个对象上
函数调用前存在多个对象,this指向距离调用自己最近的对象
function fn() {
    console.log(this.name);
};
let obj = {
    name: '行星飞行',
    func: fn,
};
let obj1 = {
    name: '听风是风',
    o: obj
};
obj1.o.func() //行星飞行

二、 隐式丢失

在特定情况下会存在隐式绑定丢失的问题,最常见的就是作为参数传递以及变量赋值
var name = '行星飞行';
let obj = {
    name: '听风是风',
    fn: function () {
        console.log(this.name);
    }
};

function fn1(param) {
    param();
};
fn1(obj.fn);//行星飞行
// obj.fn 也就是一个函数传递进 fn1 中执行,单纯传递了一个函数而已,this并没有跟函数绑在一起,所以this丢失这里指向了window。
var name = '行星飞行';
let obj = {
    name: '听风是风',
    fn: function () {
        console.log(this.name);
    }
};
let fn1 = obj.fn;
fn1(); //行星飞行

三、显式绑定(通过call、apply以及bind方法改变this的行为)

call与apply让函数从被动变主动,函数能主动选择自己的上下文,以此方法改变this指向时,指向参数提供的是null或者undefined,那么 this 将指向全局对象。
let obj1 = {
    name: '听风是风'
};
let obj2 = {
    name: '时间跳跃'
};
var name = '行星飞行';

function fn() {
    console.log(this.name);
};
fn.call(obj1); //听风是风
fn.apply(obj2); //时间跳跃
fn.call(undefined); //行星飞行
fn.apply(null); //行星飞行
fn.bind(undefined)(); //行星飞行

call、apply与bind有什么区别?

1.call、apply与bind都用于改变this绑定,但call、apply在改变this指向的同时还会执行函数,而bind在改变this后是返回一个全新的boundFcuntion绑定函数,这也是为什么上方例子中bind后还加了一对括号 ()的原因。
2.bind属于硬绑定,返回的 boundFunction 的 this 指向无法再次通过bind、apply或 call 修改;call与apply的绑定只适用当前调用,调用完就没了,下次要用还得再次绑。
let obj1 = {
    name: '听风是风'
};
let obj2 = {
    name: '时间跳跃'
};
var name = '行星飞行';

function fn() {
    console.log(this.name);
};
fn.call(obj1); //听风是风
fn(); //行星飞行
fn.apply(obj2); //时间跳跃
fn(); //行星飞行
let boundFn = fn.bind(obj1);//听风是风
boundFn.call(obj2);//听风是风
boundFn.apply(obj2);//听风是风
boundFn.bind(obj2)();//听风是风
3.call与apply功能完全相同,唯一不同的是call方法传递函数调用形参是以散列形式,而apply方法的形参是一个数组。在传参的情况下,call的性能要高于apply,因为apply在执行时还要多一步解析数组。
let obj = {
    name: '听风是风'
};

function fn(age,describe) {
    console.log(`我是${this.name},我的年龄是${age},我非常${describe}!`);
};
fn.call(obj,'26','帅');//我是听风是风,我的年龄是26,我非常帅
fn.apply(obj,['26','帅']);//我是听风是风,我的年龄是26,我非常帅

四、new绑定

function Fn(){
    this.name = '听风是风';
};
let echo = new Fn();
echo.name//听风是风

五、this的绑定优先级

显式绑定 > 隐式绑定 > 默认绑定

new绑定 > 隐式绑定 > 默认绑定

六、箭头函数的this

箭头函数中没有this,箭头函数的this指向取决于外层作用域中的this,外层作用域或函数的this指向谁,箭头函数中的this便指向谁。一旦箭头函数的this绑定成功,也无法被再次修改,可以通过修改箭头函数的外层作用域达到修改箭头函数的this。
function fn() {
    return () => {
        console.log(this.name);
    };
};
let obj1 = {
    name: '听风是风'
};
let obj2 = {
    name: '时间跳跃'
};
fn()
fn.call(obj1)(); // fn this指向obj1,箭头函数this也指向obj1
fn.call(obj2)(); //fn this 指向obj2,箭头函数this也指向obj2
Math
Math.ceil(浮点数) 小数向上取整
Math.floor(浮点数) 小数向下取整
Math.round(浮点数) 小数四舍五入
Math.max(数字,数字,数字) 取数字们中最小的
Math.max(数字,数字,数字) 取数字们中最大的
生成一个x,y之间的随机数
Math.round(Math.random()*(y-x)+x)

样式

获取当前元素样式值:元素.currentStyle.样式名 IE浏览器高光时刻
getComputedStyle(元素,null).样式名 其他浏览器
 <script>
      // obj:元素    name:样式名       获取元素对应的样式值
       function getStyle(obj,name){
         if(window.getComputedStyle){
          return getComputedStyle(obj,null)[name]
         }else{
           return obj.currentStyle[name]  //IE专属
         }
       }
    </script>

事件对象

当事件的响应函数被触发时,浏览器每次都会将一个事件对象作为实参event传递进响应函数
盒子随着鼠标移动而移动 clientX/Y pageX/Y 相对于可视窗口/整个页面的鼠标位置

事件参数的兼容

event = event||window.event
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      #box {
        width: 200px;
        height: 200px;
        background-color: cadetblue;
        position: absolute;
      }
    </style>
  </head>
  <body>
    <script type="text/javascript">
      window.onload = function () {
        var box = document.querySelector('#box')
        document.onmousemove = function (event) {
          var left = event.clientX
          var top = event.clientY
          box.style.left = left + 'px'
          box.style.top = top + 'px'
        }
      }
    </script>
    <div id="box"></div>
  </body>
</html>

事件冒泡

所谓冒泡指的就是事件的向上传导,当后代元素的事件被触发时,其祖先元素的相同事件也会被触发

取消事件冒泡

event.cancelBubble = true
event.target 当前触发事件的对象

事件委派

要实现只绑定依次事件,即可应用到多个元素上,即使元素是后添加的
–将事件绑定到元素的共同的祖先元素,后代元素事件通过冒泡传递给祖先元素
–祖先元素使用event.target.className==’name’接受期望元素绑定,其余不绑定
–减少绑定次数,提高程序性能
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      ul{
        background-color:cadetblue;
      }
    </style>
  </head>
  <body>
    <button id="btn">点击添加</button>
    <ul>
      <li><a href="#" class="link">超链接1</a></li>
      <li><a href="#" class="link">超链接2</a></li>
      <li><a href="#" class="link">超链接3</a></li>
    </ul>
    <script type="text/javascript">
      window.onload = function () {
        let btn = document.querySelector('#btn')
        var ul = document.querySelector('ul')
        btn.onclick = function () {
          var li = document.createElement('li')
          li.innerHTML = `<a href='#' class='link'>新建</a>`
          ul.appendChild(li)
        }
        ul.onclick = function (e) {
          if (e.target.className == 'link') {
            alert('你好啊')
          }
        }
      }
    </script>
  </body>
</html>

拖拽事件

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      #box {
        width: 200px;
        height: 200px;
        background-color: cadetblue;
        position: absolute;
      }
    </style>
  </head>
  <body>
    <div id="box"></div>
    <script type="text/javascript">
      window.onload = function () {
        let box = document.querySelector('#box')
        box.onmousedown = function (e) {
          // 实现鼠标拖动点在点击处点
          var ol = e.clientX - box.offsetLeft
          var ot = e.clientY - box.offsetTop
          document.onmousemove = function (e) {
            var left = e.clientX - ol
            var top = e.clientY - ot
            box.style.left = left + 'px'   //记得单位
            box.style.top = top + 'px'
          }
          document.onmouseup = function () {
            // 取消鼠标移动事件 就固定下来
            document.onmousemove = null
            document.onmouseup = null
          }
        }
      }
    </script>
  </body>
</html>

键盘事件

String.fromCharCode(数字) 键盘AC码转为字符
    <script type="text/javascript">
        document.onkeydown=function(e){
        //String.fromCharCode(数字)      数字转字符
        console.log(String.fromCharCode(e.keyCode));
        }
    </script>
方块随着方向键移动练习
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      #box {
        width: 200px;
        height: 200px;
        background-color: cadetblue;
        position: absolute;
      }
    </style>
  </head>
  <body>
    <div id="box"></div>
    <script type="text/javascript">
      window.onload = function () {
        var box = document.querySelector('#box')
        document.onkeydown = function (e) {
          event = event || window.event
          var speed = 10
          if (e.ctrlKey) {
            speed = 50
          }
          switch (e.keyCode) {
            case 38:
              box.style.top = box.offsetTop - speed + 'px'
              break
            case 37:
              box.style.left = box.offsetLeft - speed + 'px'
              break
            case 40:
              box.style.top =box.offsetTop + speed + 'px'
              break
            case 39:
              box.style.left = box.offsetLeft + speed + 'px'
          }
        }
      }
    </script>
  </body>
</html>

BOM

window:整个窗口
location:导航条信息
history:前进后退键信息
screen:屏幕信息

Json

本质就是特殊格式的字符串使得所有语言都能识别和转化,主要用于数据交互
Json对象 ‘{“属性名1″:”属性值1″,”属性名2”:”属性值2″……}’ 属性名值都要用双引号包裹
Json数组 ‘[1,2,3,4…..]’
方法: Json.parse(Json对象) 将Json对象转化为Js对象
Json.stringfy(Js对象) 将Js对象转化为Json对象
eval函数 能够用来执行一段字符串形成的js代码,并返回结果

如果eval中会将{}识别为代码块 用()包裹就不会被识别为代码块

    <script type="text/javascript">
      let str = "alert('hello')"
      eval(“("+str+")”)    //弹出hello
    </script>

JavaScript高级

数据类型

typeof 返回数据类型的字符串表示 不能判断null和object object和array
    <script type="text/javascript">
      let str = 'xy'
      console.log(typeof str === 'string')  //true
      console.log(typeof str === String)  //false
    </script>
A instanceof B A是否为B的实例 如果B函数的显示原型对象在A对象的原型链上则为true 反之false
 VC    <script type="text/javascript">
      let obj = { name: 'wkq', age: 23 }
      console.log(obj instanceof Object);   //true
    </script>
undefined和null的区别

undefined是定义但未赋值,null是定义赋值但值为null

何时使用null

初始时,对象赋值为null,用null表示将要赋值为对象

结束时 对象赋值为null 让对象成为垃圾对象被处理

数据(堆数据)|内存|变量(栈索引)

1、数据是存储在内存代表特定信息的东东
例如:var a = ‘基本数据/对象|方法/变量’ a保存的是数据/对象|方法地址/变量内存内容
2、内存是内存条通电后产生的可存储数据的空间 断电后空间和数据都消失
3、变量=变量名+变量值 对应一块小内存 变量名用来查找对应的内存 变量值就是内存中保存的数据

回调函数

定义了 没有调用 最终执行了

IIFE 函数立即执行表达式|匿名函数自调用

作用:隐藏实现,不会污染外部命名空间 可以暴露方法
<script type="text/javascript">
    // 函数自调用
      (function(){
        var a =3 
        console.log(a);   //3 
      })()
      var a = 4
      console.log(a);     //4
      
      // ;使得不会认为是整体
      ;(function(){
        var a =1
        function test(){
          console.log(++a);
        }
        window.$ = function(){
          return {
            test:test       //返回对象 对外暴露test方法
          }
        }
      })()
       $().test()
    </script>

原型

*每个函数定义时自动添加prototype属性,默认指向原型对象(空的object)
*原型对象中有个属性constructor,指向函数对象
    <script type="text/javascript">
      console.log(Date.prototype.constructor === Date)		//true
    </scripWt>
*可以给原型对象添加属性(方法)
*每个对象创建时自动添加 proto 属性,默认值为构造函数的prototype属性值
    <script type="text/javascript">
       function Fn(){

       }
       let fn = new Fn()
       console.log(Fn.prototype===fn.__proto__);		//true
    </script>

原型链

对象要使用某个属性或方法,会现在自身寻找→原型对象中寻找→原型对象的原型中寻找……直到object对象原型

原型继承

构造函数的实例对象自动拥有构造函数原型对象的属性和方法,利用的就是原型链
实例的隐式原型等于构造的显示原型 二者指向同一个原型对象(空的object)
如果显示原型重新指向,会断开之前指向的原型对象,指向新的原型对象。而隐式原型对象依然指向之前的原型对象,不会随着显示原型的重新指向而改变指向
    <script type="text/javascript">
      function A() {}
      A.prototype.n = 1
      var b = new A()
      A.prototype ={
        n:2,
        m:3
      }
      var c = new A()
      console.log(b.n,b.m,c.n,c.m);		//1 undefined 2 3
    </script>
原型链上没有 实例的隐式原型→Function的显示原型的路径 如果实例访问Function上的方法 会报错
    <script type="text/javascript">
    function F(){
      Object.prototype.a = function(){
        console.log('a()');
      }
      Function.prototype.b = function(){
        console.log('b()');
      }
    }
    var f = new F()
    f.a()
    // f.b()
    F.a()
    F.b()
    console.log(F);
      console.log(Object.prototype);
      console.log(Function.prototype);     // ƒ () { [native code] }
      console.log(Function instanceof Object);   //true    函数是对象的实例
    </script>

变量提升与函数提升 先执行变量提升再执行函数提升

变量提升
    <script type="text/javascript">
    var a =3
    function fn(){
      console.log(a);
      var a =4
    }
    fn()      //undefined
    </script>

相当于

    <script type="text/javascript">
      var a =3
      function fn() {
         var a
        console.log(a)
        a = 4
      }
      fn() //undefined
    </script>
函数提升
  <script type="text/javascript">
      fn()      //fn()			函数提升
      function fn(){
        console.log('fn()');
      }
    </script>

执行上下文

当前代码运行环境,执行代码需要哪些数据提前准备好再开始执行
    <script type="text/javascript">
      /* 测试一 */
      console.log('global begin:' + i) //undefined
      var i = 1
      foo(1)
      function foo(i) {
        if (i == 4) {
          return
        }
        console.log('foo() begin:' + i)
        foo(i + 1)
        console.log('foo() end:' + i)
      }
      console.log('global end:' + i)
      /* 测试二 */
      var c = 1
      function c(c) {
        console.log(c)   
      }
      c(2)     //报错   
		//相当于
	   var c
       function c(c) {
        console.log(c)   
      }
		c=1
		c(2)   //此时c=1  不是一个方法所以报错
      /* 测试三 */
      if (!(b in window)) {
        var b = 1
      }
      console.log(b) //undefined
    </script>

作用域和作用域链

作用域只能向外查找,不能向内查找。当需要某个属性时,向外找最近的祖先作用域里的同名属性
<script type="text/javascript">
      var a =10,b=20
      function fn(x){
        var a = 100,c=300
        console.log('fn()',a,b,c,x);
        function bar(x){
          var a =1000,d=400
          console.log('bar()',a,b,c,d,x);
        }
        bar(100)      //1000,20,300,400,100
        bar(200)      //1000,20,300,400,200
      }
      fn(10)      //100,20,300,10
    </script>
函数调用函数的情况下,考虑被调用函数的作用域向外
 <script type="text/javascript">
      var x =10
      function fn(){
        console.log(x);
      }
      function show(f){
        var x =20
        f()
      }
      show(fn)			//10
    </script>
对象属性名 不包括在函数作用域内
<script type="text/javascript">
      var fn = function () {
        console.log(fn)
      }
      fn()      //fn()
      var obj = {
        fn2: function () {
          console.log(fn2)
        },
      }
      obj.fn2() //错误   函数内部作用域并没有fn2
    </script>

闭包

定义:就是包含被引用变量的对象

嵌套情况下 内部函数引用了外部函数或变量时,产生闭包
将函数作为另一个函数的返回值 产生闭包
将函数作为实参传递给另一个函数调用 产生闭包
  <body>
    <button>按钮一</button>
    <button>按钮二</button>
    <button>按钮三</button>
    <script type="text/javascript">
      var btns = document.getElementsByTagName('button')
      for (let i = 0,length =btns.length; i < length; i++) {
        btns[i].addEventListener('click', function () {
          alert('第'+(i+1)+'按钮被按了')      //捕获i i在function之外
        })
      }
    </script>
  </body>

作用

使用函数内部的变量在函数执行完后,仍然存活在内存中(延长局部变量的生命周期
让函数外部可以操作到函数内部(局部变量)的数据

生命周期

产生:嵌套内部函数定义完成后产生
死亡:包含闭包的函数对象成为垃圾对象时

自定义JS模块

index.js
(function mymodule(){
    var xy ='wkqXY'
    function toUp(){
        console.log('toUP'+xy.toUpperCase());
    }
    function toLow(){
        console.log('toLow'+xy.toLowerCase());
    }
     window.mymodule={		//放在window上 导入该js文件即可使用
        toUp,
        toLow
     }   
})()
index.html
  <script src="./index.js"></script>
  <body>
    <script type="text/javascript">
      mymodule.toUp()
      mymodule.toLow()
    </script>
  </body>

缺点

内存泄露
函数执行完后,函数内的局部变量没有释放,占用内存时间会变长 解决:及时释放
内存泄露多了就会导致内存溢出
意外的全局变量/定时器没有清理/闭包都会导致内存泄露
内存溢出
当程序运行需要的内存超过了剩余的内存,就会抛出内存溢出的错误

秃顶题

    <script type="text/javascript">
      function fun(n,o){
        console.log(o);
        return {
          fun:function(m){
            return fun(m,n)
          }
        }
      }
      var a = fun(0)   //undefined
      a.fun(1)    
      a.fun(2)
      a.fun(3)
      var b =fun(0).fun(1).fun(2).fun(3)
      var c =fun(0).fun(1)
      c.fun(2)
      c.fun(3)
    </script>

返回一个对象的函数就是工厂函数

进程和线程

进程:程序的一次执行,它会占用一片独有的内存空间 进程之间相互独立
多进程:一应用程序可以同时启用多个实例运行
线程:是进程内的一个独立执行单元,CPU最小的调度单元
单线程:
优:顺序编程简单易懂 缺:效率低
多线程:
优:提升CPU利用率 缺:创建多线程开销/线程间切换开销/死锁和状态同步问题

关于JS

JS是单线程运行的,
Js引擎执行代码的基本流程
1、先执行初始化代码

​ *设置定时器

​ *绑定监听

​ *发送网络请求

2、后面某个时刻执行回调代码(回调函数中的代码)
Array.filter(()=>{}) //用filter中的回调过滤数组中的值,返回新数组
String.charAt(i) //返回字符串的第i-1个字符
String.padStart(x,y)返回新的字符串,表示用补全字符从左侧补全原字符串
x为字符串长度,y为补全字符
String.padEnd(x,y)返回新的字符串,表示用参数字符串从右侧补全原字符串。

原文地址:http://www.cnblogs.com/kq981024/p/16795998.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性