编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

细品原生JS从初级到高级知识点汇总(二)

wxchong 2024-07-26 22:52:48 开源技术 11 ℃ 0 评论


作者:火狼1

转发链接:https://juejin.im/post/5daeefc8e51d4524f007fb15

目录

细品原生JS从初级到高级知识点汇总(一)

细品原生JS从初级到高级知识点汇总(二)本篇

细品原生JS从初级到高级知识点汇总(三)

细品原生JS从初级到高级知识点汇总(四)

小编建议小伙们从第一篇开始,按照顺序来看,更清晰明了。

1.7.6 寄生组合继承

function Cat(name){
  Animal.call(this);
  this.name = name || 'Tom';
}
(function(){
  // 创建一个没有实例方法的类
  var Super = function(){};
  Super.prototype = Animal.prototype;
  //将实例作为子类的原型
  Cat.prototype = new Super();
})();
复制代码

1.7.7 ES6的extends继承

ES6 的继承机制是先创造父类的实例对象this(所以必须先调用super方法),然后再用子类的构造函数修改this

//父类
class Person {
    //constructor是构造方法
    constructor(skin, language) {
        this.skin = skin;
        this.language = language;
    }
    say() {
        console.log('我是父类')
    }
}

//子类
class Chinese extends Person {
    constructor(skin, language, positon) {
        //console.log(this);//报错
        super(skin, language);
        //super();相当于父类的构造函数
        //console.log(this);调用super后得到了this,不报错,this指向子类,相当于调用了父类.prototype.constructor.call(this)
        this.positon = positon;
    }
    aboutMe() {
        console.log(`${this.skin} ${this.language}  ${this.positon}`);
    }
}


//调用只能通过new的方法得到实例,再调用里面的方法
let obj = new Chinese('红色', '中文', '香港');
obj.aboutMe();
obj.say();
复制代码

1.8.高阶函数

1.8.1定义

函数的参数是函数或返回函数

1.8.2 常见的高阶函数

map,reduce,filter,sort

1.8.3 柯里化

1.定义:只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数

fn(a,b,c,d)=>fn(a)(b)(c)(d)
复制代码

2.代码实现:

const currying = fn => {
const len = fn.length
return function curr (...args1) {
    if (args1.length >= len) {
         return fn(...args1)
    }
    return (...args2) => curr(...args1, ...args2)
    }
}
复制代码

1.8.4 反柯里化

1.定义:

obj.func(arg1, arg2)=>func(obj, arg1, arg2)
复制代码

2.代码实现:

Function.prototype.uncurrying = function() {
  var that = this;
  return function() {
    return Function.prototype.call.apply(that, arguments);
  }
};
 
function sayHi () {
  return "Hello " + this.value +" "+[].slice.call(arguments);
}
let sayHiuncurrying=sayHi.uncurrying();
console.log(sayHiuncurrying({value:'world'},"hahaha"));
复制代码

1.8.5偏函数

1.定义:指定部分参数来返回一个新的定制函数的形式 2.例子:

function foo(a, b, c) {
  return a + b + c;
}
function func(a, b) {
  return foo(a,b,8);
}
复制代码

2.对象

2.1.对象的声明方法

2.1.1 字面量

var test2 = {x:123,y:345};
console.log(test2);//{x:123,y:345};
console.log(test2.x);//123
console.log(test2.__proto__.x);//undefined
console.log(test2.__proto__.x === test2.x);//false
复制代码

2.1.2 构造函数

var test1 = new Object({x:123,y:345});
console.log(test1);//{x:123,y:345}
console.log(test1.x);//123
console.log(test1.__proto__.x);//undefined
console.log(test1.__proto__.x === test1.x);//false
复制代码

new的作用: 1.创了一个新对象; 2.this指向构造函数; 3.构造函数有返回,会替换new出来的对象,如果没有就是new出来的对象

2.1.3 内置方法

Obejct.create(obj,descriptor),obj是对象,describe描述符属性(可选)

let test = Object.create({x:123,y:345});
console.log(test);//{}
console.log(test.x);//123
console.log(test.__proto__.x);//123
console.log(test.__proto__.x === test.x);//true
复制代码

2.1.4 三种方法的优缺点

1.功能:都能实现对象的声明,并能够赋值和取值 2.继承性:内置方法创建的对象继承到__proto__属性上 3.隐藏属性:三种声明方法会默认为内部的每个成员(属性或方法)生成一些隐藏属性,这些隐藏属性是可以读取和可配置的,属性分类见下面 4.属性读取:Object.getOwnPropertyDescriptor()或getOwnPropertyDescriptor() 5.属性设置:Object.definePropertype或Object.defineProperties

2.2.对象的属性

2.2.1 属性分类

1.数据属性4个特性: configurable(可配置),enumerable(可枚举),writable(可修改),value(属性值)

2.访问器属性2个特性: get(获取),set(设置)

3.内部属性 由JavaScript引擎内部使用的属性; 不能直接访问,但是可以通过对象内置方法间接访问,如:[[Prototype]]可以通过 Object.getPrototypeOf()访问; 内部属性用[[]]包围表示,是一个抽象操作,没有对应字符串类型的属性名,如[[Prototype]].

2.2.2 属性描述符

1.定义:将一个属性的所有特性编码成一个对象返回 2.描述符的属性有:数据属性和访问器属性 3.使用范围: 作为方法Object.defineProperty, Object.getOwnPropertyDescriptor, Object.create的第二个参数,

2.2.3 属性描述符的默认值

1.访问对象存在的属性

特性名 默认值 value 对应属性值 get 对应属性值 set undefined writable true enumerable true configurable true

所以通过上面三种声明方法已存在的属性都是有这些默认描述符 2.访问对象不存在的属性

特性名 默认值 value undefined get undefined set undefined writable false enumerable false configurable false

2.2.3 描述符属性的使用规则

get,set与wriable,value是互斥的,如果有交集设置会报错

2.2.4 属性定义

1.定义属性的函数有两个:Object.defineProperty和Object.defineProperties.例如: Object.defineProperty(obj, propName, desc)

2.在引擎内部,会转换成这样的方法调用: obj.[[DefineOwnProperty]](propName, desc, true)

2.2.5 属性赋值

1.赋值运算符(=)就是在调用[[Put]].比如: obj.prop = v;

2.在引擎内部,会转换成这样的方法调用: obj.[[Put]]("prop", v, isStrictModeOn)

2.2.6 判断对象的属性

名称 含义 用法 in 如果指定的属性在指定的对象或其原型链中,则in 运算符返回true 'name' in test //true hasOwnProperty() 只判断自身属性 test.hasOwnProperty('name') //true .或[] 对象或原型链上不存在该属性,则会返回undefined test.name //"lei" test["name"] //"lei"

2.3.Symbol

2.3.1概念

是一种数据类型; 不能new,因为Symbol是一个原始类型的值,不是对象。

2.3.2 定义方法

Symbol(),可以传参 var s1 = Symbol(); var s2 = Symbol(); s1 === s2 // false

// 有参数的情况
var s1 = Symbol("foo");
var s2 = Symbol("foo");
s1 === s2 // false
复制代码

2.3.3 用法

1.不能与其他类型的值进行运算; 2.作为属性名

let mySymbol = Symbol();

// 第一种写法
var a = {};
a[mySymbol] = 'Hello!';

// 第二种写法
var a = {
  [mySymbol]: 'Hello!'
};

// 第三种写法
var a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });

// 以上写法都得到同样结果
a[mySymbol] // "Hello!"
复制代码

3.作为对象属性名时,不能用点运算符,可以用[]

let a = {};
let name = Symbol();
a.name = 'lili';
a[name] = 'lucy';
console.log(a.name,a[name]); 
复制代码

4.遍历不会被for...in、for...of和Object.keys()、Object.getOwnPropertyNames()取到该属性

2.3.4 Symbol.for

1.定义:在全局中搜索有没有以该参数作为名称的Symbol值,如果有,就返回这个Symbol值,否则就新建并返回一个以该字符串为名称的Symbol值 2.举例:

var s1 = Symbol.for('foo');
var s2 = Symbol.for('foo');
s1 === s2 // true
复制代码

2.3.5 Symbol.keyFor

1.定义:返回一个已登记的Symbol类型值的key 2.举例:

var s1 = Symbol.for("foo");
Symbol.keyFor(s1) // "foo"

var s2 = Symbol("foo");
Symbol.keyFor(s2) // undefined 
复制代码

2.4.遍历

2.4.1 一级对象遍历方法

方法 特性 for ... in 遍历对象自身的和继承的可枚举属性(不含Symbol属性) Object.keys(obj) 返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性) Object.getOwnPropertyNames(obj) 返回一个数组,包括对象自身的所有可枚举和不可枚举属性(不含Symbol属性) Object.getOwnPropertySymbols(obj) 返回一个数组,包含对象自身的所有Symbol属性 Reflect.ownKeys(obj) 返回一个数组,包含对象自身的所有(不枚举、可枚举和Symbol)属性 Reflect.enumerate(obj) 返回一个Iterator对象,遍历对象自身的和继承的所有可枚举属性(不含Symbol属性)

总结:1.只有Object.getOwnPropertySymbols(obj)和Reflect.ownKeys(obj)可以拿到Symbol属性 2.只有Reflect.ownKeys(obj)可以拿到不可枚举属性

2.4.2 多级对象遍历

数据模型:

var treeNodes = [
    {
     id: 1,
     name: '1',
     children: [
       {
        id: 11,
        name: '11',
        children: [
         {
          id: 111,
          name: '111',
          children:[]
          },
          {
            id: 112,
            name: '112'
           }
          ]
         },
         {
          id: 12,
          name: '12',
          children: []
         }
         ],
         users: []
        },
      ];
复制代码

递归:

var parseTreeJson = function(treeNodes){
      if (!treeNodes || !treeNodes.length) return;

       for (var i = 0, len = treeNodes.length; i < len; i++) {

            var childs = treeNodes[i].children;

            console.log(treeNodes[i].id);

            if(childs && childs.length > 0){
                 parseTreeJson(childs);
            }
       }
    };

    console.log('------------- 递归实现 ------------------');
    parseTreeJson(treeNodes);
复制代码

2.5.深度拷贝

2.5.1 Object.assign

1.定义:将源对象(source)的所有可枚举属性,复制到目标对象(target) 2.用法:

合并多个对象
var target = { a: 1, b: 1 };
var source1 = { b: 2, c: 2 };
var source2 = { c: 3 };
Object.assign(target, source1, source2);
复制代码

3.注意: 这个是伪深度拷贝,只能拷贝第一层

2.5.2 JSON.stringify

1.原理:是将对象转化为字符串,而字符串是简单数据类型

2.5.3 递归拷贝

function deepClone(source){
  const targetObj = source.constructor === Array ? [] : {}; // 判断复制的目标是数组还是对象
  for(let keys in source){ // 遍历目标
    if(source.hasOwnProperty(keys)){
      if(source[keys] && typeof source[keys] === 'object'){ // 如果值是对象,就递归一下
        targetObj[keys] = source[keys].constructor === Array ? [] : {};
        targetObj[keys] = deepClone(source[keys]);
      }else{ // 如果不是,就直接赋值
        targetObj[keys] = source[keys];
      }
    }
  }
  return targetObj;
}  
复制代码

2.6.数据拦截

定义:利用对象内置方法,设置属性,进而改变对象的属性值

2.6.1 Object.defineProterty

1.ES5出来的方法; 2.三个参数:对象(必填),属性值(必填),描述符(可选); 3.defineProterty的描述符属性

数据属性:value,writable,configurable,enumerable
访问器属性:get,set
注:不能同时设置value和writable,这两对属性是互斥的
复制代码

4.拦截对象的两种情况:

let obj = {name:'',age:'',sex:''  },
    defaultName = ["这是姓名默认值1","这是年龄默认值1","这是性别默认值1"];
  Object.keys(obj).forEach(key => {
    Object.defineProperty(obj, key, {
      get() {
        return defaultName;
      },
      set(value) {
        defaultName = value;
      }
    });
  });

  console.log(obj.name);
  console.log(obj.age);
  console.log(obj.sex);
  obj.name = "这是改变值1";
  console.log(obj.name);
  console.log(obj.age);
  console.log(obj.sex);

  let objOne={},defaultNameOne="这是默认值2";
  Object.defineProperty(obj, 'name', {
      get() {
        return defaultNameOne;
      },
      set(value) {
        defaultNameOne = value;
      }
  });
  console.log(objOne.name);
  objOne.name = "这是改变值2";
  console.log(objOne.name);
复制代码

5.拦截数组变化的情况

let a={};
bValue=1;
Object.defineProperty(a,"b",{
    set:function(value){
        bValue=value;
        console.log("setted");
    },
    get:function(){
        return bValue;
    }
});
a.b;//1
a.b=[];//setted
a.b=[1,2,3];//setted
a.b[1]=10;//无输出
a.b.push(4);//无输出
a.b.length=5;//无输出
a.b;//[1,10,3,4,undefined];
复制代码

结论:defineProperty无法检测数组索引赋值,改变数组长度的变化; 但是通过数组方法来操作可以检测到

多级嵌套对象监听

    let info = {};
  function observe(obj) {
    if (!obj || typeof obj !== "object") {
      return;
    }
    for (var i in obj) {
      definePro(obj, i, obj[i]);
    }
  }

  function definePro(obj, key, value) {
    observe(value);
    Object.defineProperty(obj, key, {
      get: function() {
        return value;
      },
      set: function(newval) {
        console.log("检测变化", newval);
        value = newval;
      }
    });
  }
  definePro(info, "friends", { name: "张三" });
  info.friends.name = "李四";
复制代码

6.存在的问题

不能监听数组索引赋值和改变长度的变化
必须深层遍历嵌套的对象,因为defineProterty只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历,如果属性值也是对象那么需要深度遍历,显然能劫持一个完整的对象是更好的选择
复制代码

2.6.2 proxy

1.ES6出来的方法,实质是对对象做了一个拦截,并提供了13个处理方法

2.两个参数:对象和行为函数

let handler = {
    get(target, key, receiver) {
      console.log("get", key);
      return Reflect.get(target, key, receiver);
    },
    set(target, key, value, receiver) {
      console.log("set", key, value);
      return Reflect.set(target, key, value, receiver);
    }
  };
  let proxy = new Proxy(obj, handler);
  proxy.name = "李四";
  proxy.age = 24;
复制代码

涉及到多级对象或者多级数组

  //传递两个参数,一个是object, 一个是proxy的handler
//如果是不是嵌套的object,直接加上proxy返回,如果是嵌套的object,那么进入addSubProxy进行递归。 
function toDeepProxy(object, handler) {
    if (!isPureObject(object)) addSubProxy(object, handler); 
    return new Proxy(object, handler);

//这是一个递归函数,目的是遍历object的所有属性,如果不是pure object,那么就继续遍历object的属性的属性,如果是pure object那么就加上proxy
    function addSubProxy(object, handler) {
        for (let prop in object) {
            if ( typeof object[prop] == 'object') {
                if (!isPureObject(object[prop])) addSubProxy(object[prop], handler);
                object[prop] = new Proxy(object[prop], handler);
            }
        }
        object = new Proxy(object, handler)
    }

//是不是一个pure object,意思就是object里面没有再嵌套object了
    function isPureObject(object) {
        if (typeof object!== 'object') {
            return false;
        } else {
            for (let prop in object) {
                if (typeof object[prop] == 'object') {
                    return false;
                }
            }
        }
        return true;
    }
}
let object = {
    name: {
        first: {
            four: 5,
            second: {
                third: 'ssss'
            }
        }
    },
    class: 5,
    arr: [1, 2, {arr1:10}],
    age: {
        age1: 10
    }
}
//这是一个嵌套了对象和数组的数组
let objectArr = [{name:{first:'ss'}, arr1:[1,2]}, 2, 3, 4, 5, 6]

//这是proxy的handler
let handler = {
    get(target, property) {
        console.log('get:' + property)
        return Reflect.get(target, property);
    },
    set(target, property, value) {
        console.log('set:' + property + '=' + value);
        return Reflect.set(target, property, value);
    }
}
//变成监听对象
object = toDeepProxy(object, handler);
objectArr = toDeepProxy(objectArr, handler);

//进行一系列操作
console.time('pro')
objectArr.length
objectArr[3];
objectArr[2]=10
objectArr[0].name.first = 'ss'
objectArr[0].arr1[0]
object.name.first.second.third = 'yyyyy'
object.class = 6;
object.name.first.four
object.arr[2].arr1
object.age.age1 = 20;
console.timeEnd('pro')
复制代码

3.问题和优点 reflect对象没有构造函数 可以监听数组索引赋值,改变数组长度的变化, 是直接监听对象的变化,不用深层遍历

本篇未完结,请见下一篇

推荐JavaScript学习相关文章

学习 jQuery 源码整体架构,打造属于自己的 js 类库

细说RTSP实现前端直播流探索记「干货」

一文带你搞懂前端登陆设计

使用 Node.js 将图片中的苹果变成橘子「实践」

基于Canvas实现的高斯模糊(上)「JS篇」

基于Canvas实现的高斯模糊(下)「JS篇」

由浅入深,66条JavaScript面试知识点(一)

由浅入深,66条JavaScript面试知识点(二)

由浅入深,66条JavaScript面试知识点(三)

由浅入深,66条JavaScript面试知识点(四)

由浅入深,66条JavaScript面试知识点(五)

由浅入深,66条JavaScript面试知识点(六)

由浅入深,66条JavaScript面试知识点(七)

为什么 setTimeout 有最小时延 4ms ?

如何处理 Node.js 中出现的未捕获异常?

Angular v10.0.0 正式发布,不再支持 IE9/10

基于 Docker 的 SSR 持续开发集成环境实践

细聊图解webpack 指南手册

一文带你彻底搞懂 NPM 知识点「进阶篇」

细聊webpack性能优化面面观

JS实现各种日期操作方法汇总

「实践」细聊前端性能优化总结

「实践」浏览器中的画中画(Picture-in-Picture)模式及其 API

「多图」一文带你彻底搞懂 Web Workers (上)

「多图」一文带你彻底搞懂 Web Workers (中)

深入细聊前端下载总结「干货」

细品西瓜播放器功能分析(上)「实践」

细品西瓜播放器功能分析(下)「实践」

细聊50道JavaScript基础面试题「附答案」

webpack4主流程源码解说以及动手实现一个简单的webpack(上)

webpack4主流程源码解说以及动手实现一个简单的webpack(下)

细聊前端架构师的视野

细聊应用场景再谈防抖和节流「进阶篇」

前端埋点统一接入方案实践

细聊微内核架构在前端的应用「干货」

一种高性能的Tree组件实现方案「干货」

进击的JAMStack

前后端全部用 JS 开发是什么体验(Hybrid + Egg.js经验分享)上

前后端全部用 JS 开发是什么体验(Hybrid + Egg.js经验分享)中

前后端全部用 JS 开发是什么体验(Hybrid + Egg.js经验分享)下

一文带你搞懂 babel-plugin-import 插件(上)「源码解析」

一文带你搞懂 babel-plugin-import 插件(下)「源码解析」

JavaScript常用API合集汇总「值得收藏」

推荐10个常用的图片处理小帮手(上)「值得收藏」

推荐10个常用的图片处理小帮手(下)「值得收藏」

JavaScript 中ES6代理的实际用例

12 个实用的前端开发技巧总结

一文带你搞懂搭建企业级的 npm 私有仓库

教你如何使用内联框架元素 IFrames 的沙箱属性提高安全性?

细说前端开发UI公共组件的新认识「实践」

细说DOM API中append和appendChild的三个不同点

细品淘系大佬讲前端新人如何上王者「干货」

一文带你彻底解决背景跟随弹窗滚动问题「干货」

推荐常用的5款代码比较工具「值得收藏」

Node.js实现将文字与图片合成技巧

爱奇艺云剪辑Web端的技术实现

我再也不敢说我会写前端 Button组件「实践」

NodeX Component - 滴滴集团 Node.js 生态组件体系「实践」

Node Buffers 完整指南

推荐18个webpack精美插件「干货」

前端开发需要了解常用7种JavaScript设计模式

浅谈浏览器架构、单线程js、事件循环、消息队列、宏任务和微任务

了不起的 Webpack HMR 学习指南(上)「含源码讲解」

了不起的 Webpack HMR 学习指南(下)「含源码讲解」

10个打开了我新世界大门的 WebAPI(上)「实践」

10个打开了我新世界大门的 WebAPI(中)「实践」

10个打开了我新世界大门的 WebAPI(下)「实践」

「图文」ESLint 在中大型团队的应用实践

Deno是代码的浏览器,你认同吗?

前端存储除了 localStorage 还有啥?

Javascript 多线程编程?的前世今生

微前端方案 qiankun(实践及总结)

「图文」V8 垃圾回收原来这么简单?

Webpack 5模块联邦引发微前端的革命?

基于 Web 端的人脸识别身份验证「实践」

「前端进阶」高性能渲染十万条数据(时间分片)

「前端进阶」高性能渲染十万条数据(虚拟列表)

图解 Promise 实现原理(一):基础实现

图解 Promise 实现原理(二):Promise 链式调用

图解 Promise 实现原理(三):Promise 原型方法实现

图解 Promise 实现原理(四):Promise 静态方法实现

实践教你从零构建前端 Lint 工作流「干货」

高性能多级多选级联组件开发「JS篇」

深入浅出讲解Node.js CLI 工具最佳实战

延迟加载图像以提高Web网站性能的五种方法「实践」

比较 JavaScript 对象的四种方式「实践」

使用Service Worker让你的 Web 应用如虎添翼(上)「干货」

使用Service Worker让你的 Web 应用如虎添翼(中)「干货」

使用Service Worker让你的 Web 应用如虎添翼(下)「干货」

前端如何一次性处理10万条数据「进阶篇」

推荐三款正则可视化工具「JS篇」

如何让用户选择是否离开当前页面?「JS篇」

JavaScript开发人员更喜欢Deno的五大原因

仅用18行JavaScript实现一个倒数计时器

图文细说JavaScript 的运行机制

一个轻量级 JavaScript 全文搜索库,轻松实现站内离线搜索

推荐Web程序员常用的15个源代码编辑器

10个实用的JS技巧「值得收藏」

细品269个JavaScript小函数,让你少加班熬夜(一)「值得收藏」

细品269个JavaScript小函数,让你少加班熬夜(二)「值得收藏」

细品269个JavaScript小函数,让你少加班熬夜(三)「值得收藏」

细品269个JavaScript小函数,让你少加班熬夜(四)「值得收藏」

细品269个JavaScript小函数,让你少加班熬夜(五)「值得收藏」

细品269个JavaScript小函数,让你少加班熬夜(六)「值得收藏」

深入JavaScript教你内存泄漏如何防范

手把手教你7个有趣的JavaScript 项目-上「附源码」

手把手教你7个有趣的JavaScript 项目-下「附源码」

JavaScript 使用 mediaDevices API 访问摄像头自拍

手把手教你前端代码如何做错误上报「JS篇」

一文让你彻底搞懂移动前端和Web 前端区别在哪里

63个JavaScript 正则大礼包「值得收藏」

提高你的 JavaScript 技能10 个问答题

JavaScript图表库的5个首选

一文彻底搞懂JavaScript 中Object.freeze与Object.seal的用法

可视化的 JS:动态图演示 - 事件循环 Event Loop的过程

教你如何用动态规划和贪心算法实现前端瀑布流布局「实践」

可视化的 js:动态图演示 Promises & Async/Await 的过程

原生JS封装拖动验证滑块你会吗?「实践」

如何实现高性能的在线 PDF 预览

细说使用字体库加密数据-仿58同城

Node.js要完了吗?

Pug 3.0.0正式发布,不再支持 Node.js 6/8

纯JS手写轮播图(代码逻辑清晰,通俗易懂)

JavaScript 20 年 中文版之创立标准

值得收藏的前端常用60余种工具方法「JS篇」

箭头函数和常规函数之间的 5 个区别

通过发布/订阅的设计模式搞懂 Node.js 核心模块 Events

「前端篇」不再为正则烦恼

「速围」Node.js V14.3.0 发布支持顶级 Await 和 REPL 增强功能

深入细品浏览器原理「流程图」

JavaScript 已进入第三个时代,未来将何去何从?

前端上传前预览文件 image、text、json、video、audio「实践」

深入细品 EventLoop 和浏览器渲染、帧动画、空闲回调的关系

推荐13个有用的JavaScript数组技巧「值得收藏」

前端必备基础知识:window.location 详解

不要再依赖CommonJS了

犀牛书作者:最该忘记的JavaScript特性

36个工作中常用的JavaScript函数片段「值得收藏」

Node + H5 实现大文件分片上传、断点续传

一文了解文件上传全过程(1.8w字深度解析)「前端进阶必备」

【实践总结】关于小程序挣脱枷锁实现批量上传

手把手教你前端的各种文件上传攻略和大文件断点续传

字节跳动面试官:请你实现一个大文件上传和断点续传

谈谈前端关于文件上传下载那些事【实践】

手把手教你如何编写一个前端图片压缩、方向纠正、预览、上传插件

最全的 JavaScript 模块化方案和工具

「前端进阶」JS中的内存管理

JavaScript正则深入以及10个非常有意思的正则实战

前端面试者经常忽视的一道JavaScript 面试题

一行JS代码实现一个简单的模板字符串替换「实践」

JS代码是如何被压缩的「前端高级进阶」

前端开发规范:命名规范、html规范、css规范、js规范

【规范篇】前端团队代码规范最佳实践

100个原生JavaScript代码片段知识点详细汇总【实践】

关于前端174道 JavaScript知识点汇总(一)

关于前端174道 JavaScript知识点汇总(二)

关于前端174道 JavaScript知识点汇总(三)

几个非常有意思的javascript知识点总结【实践】

都2020年了,你还不会JavaScript 装饰器?

JavaScript实现图片合成下载

70个JavaScript知识点详细总结(上)【实践】

70个JavaScript知识点详细总结(下)【实践】

开源了一个 JavaScript 版敏感词过滤库

送你 43 道 JavaScript 面试题

3个很棒的小众JavaScript库,你值得拥有

手把手教你深入巩固JavaScript知识体系【思维导图】

推荐7个很棒的JavaScript产品步骤引导库

Echa哥教你彻底弄懂 JavaScript 执行机制

一个合格的中级前端工程师需要掌握的 28 个 JavaScript 技巧

深入解析高频项目中运用到的知识点汇总【JS篇】

JavaScript 工具函数大全【新】

从JavaScript中看设计模式(总结)

身份证号码的正则表达式及验证详解(JavaScript,Regex)

浏览器中实现JavaScript计时器的4种创新方式

Three.js 动效方案

手把手教你常用的59个JS类方法

127个常用的JS代码片段,每段代码花30秒就能看懂-【上】

深入浅出讲解 js 深拷贝 vs 浅拷贝

手把手教你JS开发H5游戏【消灭星星】

深入浅出讲解JS中this/apply/call/bind巧妙用法【实践】

手把手教你全方位解读JS中this真正含义【实践】

书到用时方恨少,一大波JS开发工具函数来了

干货满满!如何优雅简洁地实现时钟翻牌器(支持JS/Vue/React)

手把手教你JS 异步编程六种方案【实践】

让你减少加班的15条高效JS技巧知识点汇总【实践】

手把手教你JS开发H5游戏【黄金矿工】

手把手教你JS实现监控浏览器上下左右滚动

JS 经典实例知识点整理汇总【实践】

2.6万字JS干货分享,带你领略前端魅力【基础篇】

2.6万字JS干货分享,带你领略前端魅力【实践篇】

简单几步让你的 JS 写得更漂亮

恭喜你获得治疗JS this的详细药方

谈谈前端关于文件上传下载那些事【实践】

面试中教你绕过关于 JavaScript 作用域的 5 个坑

Jquery插件(常用的插件库)

【JS】如何防止重复发送ajax请求

JavaScript+Canvas实现自定义画板

Continuation 在 JS 中的应用「前端篇」

作者:火狼1

转发链接:https://juejin.im/post/5daeefc8e51d4524f007fb15

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表