本期系列是JavaScript的一些知识点总结,这是笔者对自己多年以来学习和使用的一些技术的巩固与复习。
已经很久没有这样从头到尾的学习过了,这系列文章也是作为一个复习的过程的一些记录,若作者本人对此有理解错误的地方也请各位朋友帮忙指出,让我们一起来复习和巩固一些曾经的一些知识吧!
学而不思则罔,思而不学则殆。
下面正式开始,每篇文章10个知识点。
第一种方式是使用 instanceof 运算符来判断构造函数的 prototype 属性是否出现在对象的原型链中的任何位置。
第二种方式可以通过对象的 constructor 属性来判断,对象的 constructor 属性指向该对象的构造函数,但是这种方式不是很安全,因为 constructor 属性可以被改写。
第三种方式,如果需要判断的是某个内置的引用类型的话,可以使用 Object.prototype.toString() 方法来打印对象的 [[Class]] 属性来进行判断。
instanceof 运算符用于判断构造函数的 prototype 属性是否出现在对象的原型链中的任何位置。
手写实现一个instanceof 的过程
/**
* 实现一个 instanceof 的过程
* @param {*} obj 对象
* @param {*} constru 构造函数
* @returns
*/
function _instanceof (obj, constru) {
let proto = Object.getPrototypeOf(obj); // 获取对象的原型
let prototype = constru.prototype; // 获取构造函数的 prototype 对象
// 判断构造函数的 prototype 对象是否在对象的原型链上
while (true) {
if (!proto) return false;
if (proto === prototype) return true;
//顺着原型链查找,直到找到原型的终点为止
proto = Object.getPrototypeOf(proto);
}
}
const obj = new String('1');
console.log(_instanceof(obj, String));
概念: js 延迟加载,也就是等页面加载完成之后再加载 JavaScript 文件。 js 延迟加载有助于提高页面加载速度。
一般有以下几种方式:
第一种方式是我们一般采用的是将 js 脚本放在文档的底部,来使 js 脚本尽可能的在最后来加载执行。
第二种方式是给 js 脚本添加 defer 属性,这个属性会让脚本的加载与文档的解析同步解析,然后在文档解析完成后再执行这个脚本文件,这样的话就能使页面的渲染不被阻塞。多个设 置了 defer 属性的脚本按规范来说最后是顺序执行的,但是在一些浏览器中可能不是这样。
第三种方式是给 js 脚本添加 async 属性,这个属性会使脚本异步加载,不会阻塞页面的解析过程,但是当脚本加载完成后立即执行 js 脚本,这个时候如果文档没有解析完成的话同样会阻塞。多个 async 属性的脚本的执行顺序是不可预测的,一般不会按照代码的顺序依次执行。
第四种方式是动态创建 DOM 标签的方式,我们可以对文档的加载事件进行监听,当文档加载完成后再动态的创建 script 标签来引入 js 脚本。
js 中现在比较成熟的有四种模块加载方案。
第一种是 CommonJS 方案,它通过 require 来引入模块,通过 module.exports 定义模块的输出接口。这种模块加载方案是服务器端的解决方案,它是以同步的方式来引入模块的,因为在服务端文件都存储在本地磁盘,所以读取非常快,所以以同步的方式加载没有问题。但如果是在浏览器端,由于模块的加载是使用网络请求,因此使用异步加载的方式更加合适。 (动态加载)
第二种是 AMD 方案,这种方案采用异步加载的方式来加载模块,模块的加载不影响后面语句的执行,所有依赖这个模块的语句都定义在一个回调函数里,等到加载完成后再执行回调函数。 require.js 实现了 AMD 规范。 (依赖前置)
第三种是 CMD 方案,这种方案和 AMD 方案都是为了解决异步模块加载的问题,sea.js 实现 了 CMD 规范。它和 require.js 的区别在于模块定义时对依赖的处理不同和对依赖模块的执行时机的处理不同。(就近依赖)
第四种方案是 ES6 提出的方案,使用 import 和 export 的形式来导入导出模块。这种方案和上面三种方案都不同。(动态加载)
CommonJS加载模块是同步的。输入的时候加载整个模块,生成一个对象,从这个对象上读取方法。子模块完成加载,才能执行后面的操作。输入的值是被输出的值的拷贝,父模块引入子模块,引入的是子模块的值拷贝,模块的内部变化无法影响这个值。
代码语法: 输入的时候加载整个模块,生成一个对象,从这个对象上读取方法,一般写在服务端的模块代码顶部。
const path = require('path');
path.dirname('模块的路径');
AMD在浏览器端异步加载,AMD推崇依赖前置,加载完模块之后就会立即执行它。
代码语法: 依赖前置,必须一开始就写好
//AMD默认推荐的是
define(['./am', './bm'], function (am, bm) {
am.todo()
bm.todo()
})
CMD在浏览器端异步加载,CMD推崇依赖就近,加载完模块不会立即执行,只是加载,等到需要的时候才会执行。
代码语法: 异步加载、依赖就近,加载完模块不会立即执行。
//CMD默认推荐的是
define(function (require, exports, module) {
//依赖就近,按需加载,只有运行到这里的时候才会进行一个加载
var am = require('./am');
am.todo();
var bm = require('./bm');
bm.todo();
});
ES6静态编译,在编译的时候就能确定依赖,编译的时候输出接口。export输出指定代码,import某个值不是整个模块。
代码语法: 静态编译,指定输出.
import am from './am';
import bm from './bm';
am.todo();
bm.todo();
//选择性导出
export function todofun () {
//todo
}
//模块导入语法为
import { todofun } from './model'
todofun();
//默认导出
export default function deftodo () {
//todo
}
//模块导入语法
import deftodo from './deftodo';
deftodo();
一个拥有 length 属性和若干索引属性的对象就可以被称为类数组对象,类数组对象和数 组类似,但是不能调用数组的方法。常见的类数组对象有 arguments 和 DOM 方法的返回结果。
函数也可以被看作是类数组对象,因为它含有 length 属性值,代表可接收的参数个数。
常见的类数组转换为数组的方法有这样几种:
Array.prototype.slice.call(arguments);
Array.prototype.splice.call(arguments,0);
Array.prototype.concat.apply([],arguments);
Array.from(arguments);
第一种情况是我们由于使用未声明的变量,而意外的创建了一个全局变量,而使这个变量一直留 在内存中无法被回收。
第二种情况是我们设置了 setInterval 定时器,而忘记取消它,如果循环函数有对外部变量 的引用的话,那么这个变量会被一直留 在内存中,而无法被回收。
第三种情况是我们获取一个 DOM 元素的引用,而后面这个元素被删除,由于我们一直保留了对 这个元素的引用,所以它也无法被回收。
第四种情况是不合理的使用闭包,从而导致某些变量一直被留在内存当中。
URI: Uniform Resource Identifier 指的是统一资源标识符
URL: Uniform Resource Location 指的是统一资源定位符
URN: Universal Resource Name 指的是统一资源名称
URI 指的是统一资源标识符,用唯一的标识来确定一个资源,它是一种抽象的定义,也就是说,不管使用什么方法来定义,只要能唯一的标识一个资源,就可以称为 URI。
URL 指的是统一资源定位符,URN 指的是统一资源名称。
URL 和 URN 是 URI 的子集,URL 可 以理解为使用地址来标识资源,URN 可以理解为使用名称来标识资源。
缓存一般只适用于那些不会更新服务端数据的请求。
所以一般 get 请求都是查找请求,不会对服务器资源数据造成修改,而 post 请求一般都会对服务器数据造成修改。
即一般会对 get 请求进行缓存,很少会对 post 请求进行缓存。
当然也可以理解为,缓存的请求一般是只读的。有对数据进行操作或者编辑的请求是几乎不会被缓存的。
预加载:提前加载图片,当用户需要查看时可直接从本地缓存中渲染。
懒加载:懒加载的主要目的是作为服务器前端的优化,减少请求数或延迟请求数。
两种技术的本质:两者的行为是相反的,一个是提前加载,一个是迟缓甚至不加载。 懒加载对服务器前端有一定的缓解压力作用,预加载则会增加服务器前端压力。
懒加载的实现原理是,将页面上的图片的 src 属性设置 为空字符串,将图片的真实路径保存在一个自定义属性中,当页面滚动的时候,进行判断,如果 图片进入页面可视区域内,则从自定义属性中取出真实路径赋值给图片的 src 属性,以此来实 现图片的延迟加载。
预加载指的是将所需的资源提前请求加载到本地,这样后面在需要用到时就直接从缓存取资源。 通过预加载能够减少用户的等待时间,提高用户的体验。我了解的预加载的最常用的方式是使用 js 中的 image 对象,通过为 image 对象来设置 scr 属性,来实现图片的预加载。
许多知识久了没看还是可能会忘记的,抽一点时间出来,偶尔复习一下。让我们一起进步,加油~
上面就是本期的全部内容了,你学废了吗?
有问题请留言或者@博主,谢谢支持o( ̄︶ ̄)o~
感谢您的阅读,如果此文章或项目对您有帮助,请扫个二维码点个关注吧,若可以的话再给个一键三连吧!
公众号阅读的朋友可以点一下右下角的在看和分享哦。
更多信息请关注公众号: “笔优站长”
