js

317 阅读3分钟

typeof()

  1. 值类型 "underfind" "string" "number" "boolean" "symbol"
  2. 函数 "function"
  3. 引用类型 "Object" 数组 [] 对象 {} 注意:null 指向空地址 特殊引用类型

字符串拼接

数字相加 = 数字
字符串相加 = 拼接

什么时候用 === 什么时候用==

null == underfined
== 运算符会类型转换
判断是否等于null或者underfined之外,其他一律用 ===

if else 也会变量转换
&&  || !

class函数继承

class Test{
   constructor(name){
       this.name = name
   }
   eat(){
       console.log(`${this.name} eat something`)
   }
}
class Student extends Test{
    constructor(name, number){
        super(name);//执行父类的构造函数
        this.number = number;
    }
    sayHi(){
        console.log(`姓名${this.name} 学号${this.number}`)
    }
}
const  sunny = new Student('苏珊娜','21')
console.log(sunny.name);

手写jquery

class jQuery{
    constructor(selector){
        const result = document.querySelectorAll(selector);
        const length = result.length;
        for(let i = 0; i < length;i++){
            this[i] = result[i]
        }
        this.length = length
        this.selector = selector
    }
    get(index){
        return this[index]
    }
    each(fn){
        for(let i = 0;i < this.length;i++){
            const item = this[i];
            fn(item);
        }
    }
    on(type, fn){
        return this.each(item =>{
            item.addEventListener(type, fn, false)
        })
    }
}
const $p = new jQuery('p');    
$p.get(1);
$p.each((item) => console.log(item.nodeName));
$p.on('click',() => console.log('clicked'));

作用域

全局作用域
函数作用域
块级作用域(ES6新增)  let const 外部不能使用

闭包

  • 缺点:会造成内存泄露
  • 优点:模块化开发防止全局变量 属性私有化
function test() {
    var num = [];
    for(var i = 0;i < 10; i++){
        (function(j){
            num[i] = function(){
                console.log(j);
            }
        }(i))//闭包解决办法 立即执行函数
    }
    return num;
}
var gettest = test();
for(var j = 0;j < 10; j++){
    gettest[j]();
}
function createCache(){
    const data  = {};
    return{
        set:function(key, val){
            data[key] = val;
        },
        get: function(key){
            return data[key];
        }

    }
}
const item = createCache();
item.set('a',800);
console.log(item.get('a'));//800

1.函数作为参数
function print(fn){
    const a = 100;
    fn();
}
const a = 200;
function fn(){
    console.log(a);
}
console.log(print(fn))//200
//所有自由变量的查找是在函数定义的地方,不是函数执行的地方,向上级作用于查找不是执行的地方
2.函数作为返回值
function create(){
    const a = 100;
    return function(){
        console.log(a)
    }
}
const a = 200;
const fn = create();
fn();//100

this

this的作用
1.当做函数调用 2.当做构造函数调用 3.当做属性值调用

this取什么值是在函数执行时确认的
const zhansan  = {
    name:'张三',
    sanHi(){
        console.log(this);
    },
    wait(){
        setTimeout(function(){ 
            console.log(this);//指向window
        })
        // setTimeout(() => {
        //     console.log(this);
        // },); //箭头函数指向他的上级作用域
    }
}
this的不同应用场景
1.当做普通函数被调用
2.通过call apply bind 改变this指向
3.通过对象调用 返回对象本身
4.class的方法中调用 指向他的实例
5.箭头函数会找他的上级作用域

手写bind()方法
Function.prototype.bind1 = function (){
    const list = Array.prototype.slice.call(arguments);
    const t = list.shift();
    const self = this;//this就是fn1
    return function(){
        return self.apply(t, list)
    }
}
function fn1(a,b,c){
    console.log('this',this);
    console.log(a,b,c);
    return 'this is fn1'
}
const fn2 = fn1.bind({x:100},10,20,30);
console.log(fn2())

异步和单线程

同步和异步的区别是什么?
基于JS是单线程语言
异步不会阻塞代码执行
同步会阻塞代码的执行

前端异步的使用场景有哪些?
1.网络请求,如ajax图片加载
2.定时任务,如setTimeout

异步
console.log(100);
setTimeout(() => {
    console.log(888);
}, 1000);
console.log(400);

同步
console.log(100);
alert(200);// 必须等它执行了才会执行下面 
console.log(400);

预编译

1.函数声明整体提升  
2.变量 声明提升
3.没有声明就使用的变量为全局变量 全局变量为window所有
2.创建AO 
1.形参和变量声明名作为AO对象属性名 2.值为undefined 3.形参实参值统一4.找函数声明名为函数体

立即执行函数

1.只有表达式才能被执行 ()执行符 函数表达式立即执行会失去函数索引
2.函数声明(加 + - ! ())可以变成表达式
  var x = 1;
  if (function f() { }) {//typeof()是唯一可以返回没有定义的变量
      x += typeof f
  }//'1undefined'

对象

构造函数原理 ---构造函数与其他函数的区别----大驼峰式 Person
new1.在函数体最前面隐式的创建this空对象 并给他添加原型链
2.执行函数体
3.隐式的返回this

包装类
new Number() new String() new Boolean()
var str = 'abcd';
str.length = 2 //str = 'abcd'
会进行隐式的转换调用new String('abcd').length = 2; 并delete
str.length //4

toString()

null 和 undefined 没有toString()方法是因为没有原型 而数字会进行包装类

inherit 继承函数

Father.prototype = {
    lastName : '父亲的原型'
}
function Father(){
    this.name = '父亲'
}
function Son(){
    this.name = '儿子'
}
function inherit(Target, Origin){
    function F(){};
    F.prototype = Origin.prototype;
    Target.prototype = new F();
    Target.constructor = Target;
}
inherit(Son, Father)

var father = new Father();
var son = new Son();

对象的枚举 遍历

1.for in
2.hasOwnProperty()
3.in 
4.instanceof  A对象的 原型链上 有没有B的 原型
var obj ={ name:'Bob' }//obj.name ==  obj['name'] 属性查看
var liang= {
    color1 : 'red',
    color12 : 'green',
    getColor : function(num){
        console.log(this['color' + num])
    }
}
var obj ={name:'xiaohong', eag:'15',color:'green'__proto__:{dudu:666} }
for(var key in obj){ 
  if(obj.hasOwnProperty(key)){ //判断属性是否是自己的 原型上的不要
      console.log(obj[key])  
  }
} 枚举时不能写obj.key因为会把它当变量

'dudu' in obj //true 只要是自己身上的属性都返回true

function F(){
}
var f = new F()

f instanceof F  f instanceof Object //true
区别数组的3种方法
1.Object.prototype.toString.call()
2.instanceof
3.constructor

浅拷贝与深拷贝的区别

浅拷贝 
方法1 for in
方法2 let newlist = Object.assign({},list)
方法3 let newlist = {...list}

深拷贝
方法1.obj1 = JSON.parse(JSON.stringify(obj))
方法1.function deepClone(Orinig, Target){
    var Target = Target || {};
    var tostr = Object.prototype.toString;
    for(var key in Orinig){
        if(Object.hasOwnProperty(key)){
            if(typeof(Orinig[key]) !== 'null' && typeof(Orinig[key]) == "object"){	
            // origin[key] instanceof Array 
            	tostr.call(Orinig[key]) == "[object Array]" ?
                	Target[key] = []:Target[key] = {}
                	deepClone(Orinig[key], Target[key])      
            }else{
                Target[key] = Orinig[key]
            }
        }
    }
    return Target;
}
deepClone(obj, obj1)

call() apply() bind()

相同 改变this指向 借用用别人的方法 干自己的事 不同 传参列表不同,且bind()是新函数返回

function Person(name, age){
    this.name = name;
    this.age = age;
}
function Father(color){
    this.color = color;
}
function Student(name, age ,color , tel , sex ){
	Person.apply(this,[name, age])
    Father.call(this, color)
    this.tel = tel;
    this.sex = sex;
}
var student = new Student('huang', 100, 'red', 15268883061, 'male');

const fn2 = fn1.bind({x:200})
fn2()

callee caller 区别

arguments.callee  解决递归自身名字问题
caller 返回自身在哪个函数里执行
function Test(n){
	return n * arguments.callee *(n-1)
}
arguments.callee == Test 指向函数自身引用

function test(){ 
    dome()
}  
function dome(){ 
    dome.caller  //== Test 返回自身在哪个函数里执行
}
test();

重写push方法

Array.prototype.push = function(){
    for(var i = 0 ; i < arguments.length ; i++){
        this[this.length] = arguments[i]
    }
    return this.length;
}

类数组

属性为索引属性(数字),必须有length属性,最好加上push

好处是把数组对象特效拼在一起
坏处 方法需要手动添加
var obj = {
  1:'a'
  2:'b'
  'length':2
  'push':Array.prototype.push
  'splice':Array.prototype.splie
}
push 的时候 
Array.prototype.push = function(target){
	obj[obj.length] = target 
	obj.length++
}
通过varwindow上构造的基本属性,叫不可配置属性 不能直接删除
var a = 123;
window.a / detele 无效 
arguments是个类数组   typeOf(arguments) == object

try{} catch(e)

try{
  console.log('a')
  console.log(b)----- 会直接跳catch执行 try里面发生错误 后面代码不执行 
  console.log('c')
}catch(e){//error
  console.log('error.name') ---允许操作错误信息
}

理解json

json是js内置对象也是数据格式   内置两个方法 实现深拷贝
JSON.stringfiy() 解析为字符串
JSON.parse() 解析为json

js的内置函数有哪些

Function
String
Array
Date
Boolean
Number
Error
Object
RegExp

异步调用

前端调用异步状态
1.延迟任务 2.ajax调用数据 3.事件绑定
setTimeout(()=>alert ('hello world'),3000)

类型转换

1.强制类型转换
parseInt parseFloat toString
2.隐式
+字符串拼接、== 、if语句、逻辑运算 如 && ||

描述创建一个对象的过程

1.创建空对象绑定this 
2.通过原型 链接到原型链
3.执行逻辑代码
4.返回对象(所以实例不用返回

可以跨域的3个标签

<img src=''>    <script src=''>    <link  href=''>

Date

Date.now() //获取当前时间毫秒数
var dt = new Date()
dt.getTime()  		//获取毫秒数
dt.getFullYear()  	//年
dt.getMonth()		//月(0-11)
dt.getDate()		//日(0-31)
dt.getHours()		//小时(0-23)
dt.getMinutes()		//分钟(0-59)
dt.getSeconds()		//秒(0-59)
toISOString()		//YYYY-MM-DDTHH:mm:ss.sssZ 使用 ISO 标准返回 Date 对象的字符串格式:

提示页面性能的办法

1.减少http请求
2.异步加载
3.浏览器缓存
4.css中避免使用表达式

什么是浏览器缓存

资源文件在电脑磁盘上的备份

http的主要特点是什么

无连接 无状态

http常见的请求有哪些

1.GET获取资源 
2.POST传输资源  
3.PUT更新资源 
4.DELETE删除资源 
5.HEAD获取头部首部

GET 和 POST的差别

优势:
GET 请求会被浏览器会自动缓存 POST不会,除非手动设置
GET 在浏览器回退时无害,而POST会重新请求
劣势:
GET 请求不安全 参数在URL上 保存在浏览器中
GET 请求在url中参数有限制,POST没有

前端捕捉错误的方法

即时错误的捕捉
try-catch
window.onerror

数组的常用方法

改变数组

  • shift() 删除第一项 返回被删除的值
  • pop() 删除最后一项 返回被删除的值
  • unshift() 在数组前面添加元素 返回数组长度
  • push() 在数组后面添加元素 返回数组长度
  • sort() 数组排序 a-b/b-a
  • splice() 剪切(开始的下标,删除的个数,添加的个数) 返回数组
  • reverse() 颠倒顺序 返回颠倒后的数组
  • forEach() 遍历数组 无返回值

不改变数组

  • join() 转换为字符串
  • toString() 转换为string类型
  • indexOf() 查找数组中是否包含某个元素 没有返回 -1 有返回 0
  • includes() 查找数组中是否包含某个元素 返回true/false
  • some() 数组是否至少有一项满足条件 true/false
  • every() 数组是否所有项都满足条件 true/false 纯函数:不会改变原数组,没有副作用,且返回的是数组
  • slice() 切片(从该下标开始截取,截取到下标) 返回区间内的数组
  • filter() 过滤符合条件的元素 返回处理后的数组
  • concat() 拼接 返回拼接后数组
  • map() 遍历数组 返回处理后的数组

字符串的常用方法

  • split() 拆分字符串
  • indexOf()查找 未找到返回-1
  • lastIndexOf() 从后朝前查找未找到返回-1
  • slice() 截取字符串 开始到结束
  • replace() 替换字符串
  • toUpperCase()字符串转大写
  • toLowerCase()字符串转小写
  • concat() 连接字符串

for in for of的区别

for in 返回下标(key) for of 返回值(value)

Set Map 的用处

Set
let a = new Set([1,2,3,2,1]) 数组去重
console.log(a)//1,2,3
add():添加某个值,返回 Set 结构本身。
delete():删除某个值,返回一个布尔值,表示删除是否成功。
has():返回一个布尔值,表示该值是否为Set的成员。
clear():清除所有成员,没有返回值。

Map
let tt = new Map([['gongzi',11],['fusu',22],['xiaobai',33]])
console.log(a.get('xiaobai')) //33
get() 获取值
set() //添加值
has();    // 查询是否存在
delete(); // 删除一个值
clear();   // 清空所有成员 无返回

方法
values()展示value
keys()展示key
entries() key和value一起展示
forEach()循环

主流浏览器

IE       
chrome
safari
firefox
opera

es5严格模式

'use strict'  逻辑最顶端 (页面/局部函数顶端)
以下es3不能使用
1.with(obj){ //改变作用域链 直接的AO	
}
2.arguments.callee    caller
3.变量必须声明
4.局部this必须赋值 预编译局部this指向空  全局this还是指向windo
5.函数里不能有重复参数及对象里不能有重复属性
6.eval()改变作用域 直接执行字符串代码

js异步加载

1.defer 在dom渲染时并行加载,等dom渲染完了,多个按加载顺序执行,再执行DOMContentLoaded事件
2.async 在dom渲染时并行加载,加载完就执行,多个无顺序,加载时候不会阻碍dom渲染,执行时会
3.script标签 会优先下载并执行 再执行render three
    1.var script = docunment.createElement('script');
    2.script.Type = 'text/javascript'
    //判断是否加载完成
    3.script.scr = 'dome.js' //预加载
    document.body.appendChild(script);//使用
    script.onload = function(){}//保证下载完执行    

浏览器出生时候一系列的事
document.readyState 页面的新生的实时状态
加载时 loading
解析完 interactive
加载执行完 complete
$(document).ready(function(){}) 解析完就
window.onload 全加载完才

跨域

1.JSONP 
前台做限制
同源策略:协议 域名端口号 不一样即发生跨域
动态创建一个<script>标签 把请求通过参数发出去默认为callback 
后端用参数的值作为函数名 js对象改为js代码作为参数返回给前端 以函数调用返回给前端 

弊端
JSONP 后台需要做改动
只支持Get
发出去的不是XHR请求

2.被调用方解决(后端解决)
服务端在响应头里面
Access-Control-Allow-Origin:* 允许域名才能跨域,* 所有的域名都能访问,但是带cookie必须是全匹配,必须得指定域名

Access-Control-Allow-Methods:* 允许哪个方法访问我

Access-Control-Allow-Credentials:true/false 表示是否允许发送cookie,即cors请求中不包括cookie,设为true,即表示服务器明确cookie可以包含在请求中,一起发送给服务器

带Cookie的跨域
送的域名是调用方的Cookie
Access-Control-Allow-Origin:必须写域名
服务端判断Access-Control-Allow-Origin是否为空设置 

自定义头的时候判断
服务端判断Access-Control-Allow-Headers是否为空设置 


简单请求和非简单请求

1.简单请求 先执行后判断
方法为 GET POST HEAD 
请求header里面没有自定义头
Content-Type 为
text/plain
multipart/form-data
application/x-www-form-urlencoded
2.非简单请的cors请求,是发送请求之后先在服务端 "预检" 一遍,预检发送的请求方法是 OPTIONS ,看看服务端是否允许跨域,假如我们使用PUT请求方法向后台发送请求,属于非简单请求,需要在node后台设置允许跨域

Access-Control-Max-Age: 18000 设置预检命令的缓存时间
disable cache 可以使缓存消失

得在前台页面写一个自定义的报文请求头属性content-type

方法为 PUT delete 
Content-Type 为
发送json格式的ajax请求
自带定义头的ajax请求

2.调用方(前端解决)
多个域名指向


ES6

let const 
1.先声明才能使用 
2.不允许重复声明 
3.不存在变量提升
4.块级作用域
5.不属于顶级对象window
const 常量 原始数据(栈)不可变 对象(堆)可以改变因为地址一样  
Object.freeze(obj) 浅冻结 深冻结需要typeof 判断 Object.key()生成键数组

箭头函数没有this
沿着作用域链向上找this