JavaScript知识点总结

210 阅读3分钟

编辑角色 权限编辑 权限查询 路由赋值

this.$router.push({name:'monitoringDetail', query: {id: id}});
this.$router.push({ name: 'home', params: { userId: wise }})
this.$router.replace('position');
this.$router.go(-1);
const {href} = this.$router.resolve({ name: 'srvbotReqDetail', query})
window.open(href, '_blank');

执行上下文

变量/函数提升 确认作用域/链 确认this指向 构造函数 原型/链 数据类型(stack、heap)

作用域和作用域链(闭包)

全局作用域 函数作用域 块级作用域

变量提升/函数提升(先提升函数声明再提升变量声明)

(下面实例结果是 fun function)(ERROR 'fun' has already been declared)

let fun = ‘fun’
function fun () {}

this指向

function Test () { return this }
Test() this指向window对象
new Test() this指向实例对象

  • node全局
    name = 'node.js' 指向global
    this.name = ‘node.js’ 指向 module.exports
    function test() {this === global} 指向global
  • 浏览器全局
    name = 'win' 指向 window
    Object 键值遍历输出
    let obj = {
        name: "zhu",
        age: 24,
        [Symbol("bar")]: "symbol-bar"
    }
    
  1. Symbol属性
  2. Object.defineProperty(obj, "age", { enumerable: false }) 不可枚举
  3. obj.proto = { fa: "father" } 原型上的属性
for (let key in obj) {}
for (let key of obj) {}
Object.keys(obj) name
Object.getOwnPropertyNames(obj) name age
Object.getOwnPropertySymbols(obj) Symbol("bar")
Reflect.ownKeys(obj) name age Symbol("bar")

内存泄漏 -> 内存溢出

  1. 意外的全局变量
  2. 被遗忘的计时器或回调函数
  3. 脱离 DOM 的引用
  4. 闭包

箭头函数和普通函数的区别:

  1. 定义方式 普通function test(){}
    箭头()=>{}
  2. 箭头函数不能用于构造函数
    function Person(name,age){
        this.name=name;
        this.age=age;
    }
    let admin=new Person("恩诺小弦",18);
    console.log(admin.name);
    console.log(admin.age);
    
  3. this指向不同
    1. 箭头函数的 this 永远指向其上下文的 this ,任何方法都改变不了其指向 fn.call(obj,a,b) fn, fn.bind(obj,[a,b]) , fn.apply(obj,a,b)
      document.onclick = fn.call(obj);立即执行fn,click执行的是fn的返回值
      document.onclick = fn.bind(obj);预处理this指向,click执行的是fn
    2. 普通函数的this指向调用它的那个对象

原型和原型链(Class)

JavaScript的原型继承实现方式

  • 定义新的构造函数,并在内部用call()调用希望“继承”的构造函数,并绑定this;
  • 借助中间函数F实现原型链继承,最好通过封装的inherits函数完成;
  • 继续在新的构造函数的原型上定义新方法。
function inherits(Child, Parent) {
    var F = function () {};
    F.prototype = Parent.prototype;
    Child.prototype = new F();
    Child.prototype.constructor = Child;
}

es6 class extends

super 指向父类

Class Rabbit extends Animal {
    hide() {
        alert(`${this.name} hides!`);
    }
    stop() {
        super.stop();//调用父类的stop函数
        this.hide();//然后隐藏
    }
}

js的数据类型有哪些,存储在哪

  1. 基本数据类型,存在栈中(stack)
    1. Boolean(B)
    2. String(S)
    3. underfined(N)
    4. Null(N)
    5. Number(N)
    6. symbol(ES6的)
  2. 引用数据类型(复杂类型),存在堆中(heap)
    在栈中存指针,指向堆中的地址
    Array Object Date RegExp Function

深浅拷贝(数据类型的原因)

let obj = {a: 1, b: 2};

浅:

  1. Object.assign()
    Object.assign({}, obj);
  2. 解构赋值
    {...obj};

深:

  1. JSON.parse 和JSON.stringfy
    function deepClone(obj){
        let _obj = JSON.stringify(obj),//把JSON对象转化为字符串
        objClone = JSON.parse(_obj);//把JSON字符串转化为对象
        return objClone
    }
    export default deepClone
    
  2. 层级更深
    递归 or lodash.cloneDeep(obj) lodash库
    let obj = {
        a: ‘a’,
        b: ‘b’,
        c: { cc: ‘cc’}
    }
    newObj = obj; 赋值 new变,都变
    newObj = { ...obj }; 浅拷贝new变,a、b不变,c.cc跟着变
    _obj = JSON.stringify(obj); newObj = JSON.parse(_obj); new变old不变
    

new 操作符做了什么

  1. 创建一个空对象
    var obj = new Object();
  2. 设置原型链
    (当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性),指向构造函数的原型对象)
    obj.proto= Func.prototype;
  3. 让Func中的this指向obj,并执行Func的函数体
    (创建新的对象之后,将构造函数的作用域赋给新对象(因此this就指向了这个新对象))
    var result =Func.call(obj);
  4. 判断Func的返回值类型:
    如果是值类型,返回obj。如果是引用类型,就返回这个引用类型的对象 if (typeof(result) == "object"){ func=result; }else{ func=obj;; }

原生new

function Foo(name) {
    console.log(this)
    this.name = name;
    console.log(this)
    return this;
};
function _new(Func, ...args) {
    let obj = {};
    obj.__proto__ = Func.prototype;
    let result = Func.call(obj, ...args);
    return result || obj;
}

原生call

Function.prototype._call = function(arg, ...args) {
    arg.fn = this;
    let res = arg.fn(...args);
    delete arg.fn;
    return res;
};

instanceof原理

function instance_of(L, R) { // L即stu ;  R即Person        
    var O = R.prototype; // O为Person.prototype     
    L = L.__proto__; // L为stu._proto_,现在指向的是per实例对象
    while (true) { // 执行循环
        if (L === null) return false; // 不通过
        if (O === L) return true;
        L = L.__proto__; // 令 L = stu._proto_._proto_,执行循环
    } // stu._proto_ ._proto_,看图示知:
} // 指的就是Person.prototype,所以也返回true

加密问题

  1. 哈希HASH
    • MD5
    • SHA 加密
    • HMAC 加密
  2. 对称加密
    • DES(Data Encryption Standard):数据加密标准(现在用的比较少,因为它的加密强度不够,能够暴力破解)
    • 3DES:原理和DES几乎是一样的,只是使用3个密钥,对相同的数据执行三次加密,增强加密强度。(缺点:要维护3个密钥,大大增加了维护成本)
    • AES(Advanced Encryption Standard):高级加密标准,目前美国国家安全局使用的,苹果的钥匙串访问采用的就AES加密。是现在公认的最安全的加密方式,是对称密钥加密中最流行的算法。
  3. 非对称加密
    • RSA 加密(jsencrypt.js包)
    • sm2(公司一账通服务)
  4. https (http+ssl)
    非对称加密+对称加密

前端监控埋点(事件追踪)

  1. 目的 数据监控(监听用户行为)
    性能监控(Performance)
    异常监控(sentry.js、Better.js、Logan)
    sentry:配合 webpack 构建时的 SourceMaps 进行异常定位)
  2. 方案
    代码埋点
    可视化埋点(百度统计、友盟)
    无痕埋点(全埋点)
  3. 埋点属性、事件、周期、数据加密、可视化展示