0
点赞
收藏
分享

微信扫一扫

前端小知识点扫盲笔记记录11

前言

我是歌谣 放弃很容易 但是坚持一定很酷 微信公众号关注前端小歌谣带你进入前端巅峰交流群 今天继续对前端知识的小结

异步和同步转换第二种

<!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>异步和同步转换</title>
</head>
<body>
  <script>
    async function fangfang() {
      return new Promise((resolve)=>{
        setTimeout(() => {
          resolve("我给你钱")
      },1000)
    })
  }
  function geyao() {
      return "我去买东西"
    }
   async function test() {
      let qian=await fangfang();
      let dongxi=await geyao();
      console.log(qian,"qian")
      console.log(dongxi,"dongxi")
    }
    test()
  </script>
</body>

</html>

弹出a标签

<!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>
</head>
<body>
    <script>
        var a=document.getElementsByTagName("a");
        for(var i=0;i<a.length;i++){
            a[i].onclick=(function(i){
                console.log(i)
            })(i)
        }
    </script>
</body>
</html>

强制缓存

//强制缓存
		<!-- Cache-Control: 在 Response Headers 中。 控制强制缓存的逻辑。 例如
		Cache-Control: max-age=3153600(单位是秒) Cache-Control 有哪些值:
		max-age:缓存最大过期时间。
		no-cache:可以在客户端存储资源,每次都必须去服务端做新鲜度校验,来决定从服务端获取新的资源(200)还是使用客户端缓存(304)。
		no-store:永远都不要在客户端存储资源,永远都去原始服务器去获取资源。 -->
		//协商缓存 
        <!-- 服务端缓存策略。 服务端判断客户端资源,是否和服务端资源一样。
		一致则返回 304,否则返回 200 和最新的资源。 资源标识: 在 Response
		Headers 中,有两种。 Last-Modified:资源的最后修改时间。
		Etag:资源的唯一标识(一个字符串,类似于人类的指纹)。 Last-Modified:
		服务端拿到 if-Modified-Since
		之后拿这个时间去和服务端资源最后修改时间做比较,如果一致则返回 304
		,不一致(也就是资源已经更新了)就返回 200 和新的资源及新的
		Last-Modified。 Etag: 其实 Etag 和 Last-Modified 一样的,只不过 Etag
		是服务端对资源按照一定方式(比如
		contenthash)计算出来的唯一标识,就像人类指纹一样,传给客户端之后,客户端再传过来时候,服务端会将其与现在的资源计算出来的唯一标识做比较,一致则返回
		304,不一致就返回 200 和新的资源及新的 Etag。 两者比较: 优先使用 Etag。
		Last-Modified 只能精确到秒级。 如果资源被重复生成,而内容不变,则 Etag

强缓存和协商缓存

<!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>强缓存和协商缓存</title>
	</head>
	<body>
		<script>
			//         缓存可分为强缓存和协商缓存。
			//    浏览器进行资源请求时,会判断response headers是否命中强缓存,如果命中,直接从本地读取缓存,不会向服务器发送请求,
			//    当强缓存没有命中时,会发送请求到服务端,判断协商缓存是否命中,如果命中,服务器将请求返回,不会返回资源,告诉浏览器从本地读取缓存。如何不命中,服务器直接返回资源
			//    区别: 强缓存命中,不会请求服务器,直接请求缓存;协商缓存命中,会请求服务器,不会返回内容,然后读取缓存;

			// 强缓存又分为Expires 和 Cache-Control
			// Expires,该值是一个GMT时间格式个字符串,浏览器进行第一次请求时,服务器会在返回头部加上Expires,下次请求,如果在这个时间之前则命中缓存,

			// app.get('/', (req, res) => {
			// 	const cssContent = path.join(__dirname, './html/index.html')
			// 	fs.readFile(cssContent, function (err, data) {
			// 		res.setHeader(
			// 			'Expires',
			// 			new Date(Date.now() + 2592000000).toUTCString()
			// 		)
			// 		res.end(data)
			// 	})
			// })
			//             Cache-Control ,该值是利用max-age判断缓存的生命周期,是以秒为单位,如何在生命周期时间内,则命中缓存
			//             app.get('/', (req, res) => {
			//     const cssContent = path.join(__dirname, './html/index.html');
			//     fs.readFile(cssContent, function(err, data) {
			//         res.setHeader("Cache-Control", "max-age=0");
			//         res.end(data);
			//     })
			// });
			//             协商缓存
			// 协商缓存利用Last-Modified , If-Modified-Since 和 ETag , If-None-Match来实现
			// Last-Modified , If-Modified-Since
			// Last-Modified: 表示为为实体头部部分,response返回,表示为资源的最后更新时间

			// If-Modified-Since:通过比较两次的时间判断,资源在请求期间是否有修改,假如没有修改,则命中协商缓存,浏览器从缓存中读取资源,如果没有命中,资源有过修改,返回新的Last-Modified时间和服务器资源
			//     app.get('/', (req, res) => {
			//     const cssContent = path.join(__dirname, './html/index.html')
			//     fs.stat(cssContent, (err, start) => {
			//         if (req.headers['if-modified-since'] === start.mtime.toUTCString()) {
			//             res.writeHead(304, 'Not Modified');
			//             res.end();
			//         } else {
			//             fs.readFile(cssContent, function (err, data) {
			//                 let lastModified = start.mtime.toUTCString();
			//                 res.setHeader('Last-Modified', lastModified);
			//                 res.writeHead(200, 'OK');
			//                 res.end(data);
			//             })
			//         }
			//     })

			// });
			// 复制代码ETag , If-None-Match
			// 有些情况下仅判断最后修改日期来验证资源是否有改动是不够的:
			// 1,存在周期性重写某些资源,但资源实际包含的内容并无变化;
			// 2,被修改的信息并不重要,如注释等;
			// 3,Last-Modified无法精确到毫秒,但有些资源更新频率有时会小于一秒。

			// ETag:为相应头部字段,表示资源内容的唯一标识,随服务器response返回;

			// If-None-Match: 服务器比较请求头中的If-None-Match和当前资源中的etag是否一致,来判断资源是否修改过,如果没有修改,则命中缓存,浏览器从缓存中读取资源,如果修改过,服务器会返回新的etag,并返回资源;
			// app.get('/home', (req, res) => {
			//     const cssContent = path.join(__dirname, './html/index.html')
			//     fs.stat(cssContent, (err, start) => {
			//         let etag = md5(cssContent);
			//         if (req.headers['if-none-match'] === etag) {
			//             res.writeHead(304, 'Not Modified');
			//             res.end();
			//         } else {
			//             fs.readFile(cssContent, function (err, data) {
			//                 res.setHeader('Etag', etag);
			//                 res.writeHead(200, 'OK');
			//                 res.end(data);
			//             })
			//         }
			//     })
			// });
		</script>
	</body>
</html>

性能优化

代码层面: 1防抖和节流(resize,scroll,input)。 减少回流(重排)和重绘。 事件委托。 css 放 ,js 脚本放 最底部。 减少 DOM 操作。 按需加载,比如 React 中使用 React.lazy 和 React.Suspense ,通常需要与 webpack 中的 splitChunks 配合。 构建方面: 压缩代码文件,在 webpack 中使用 terser-webpack-plugin 压缩 Javascript 代码;使用 css-minimizer-webpack-plugin 压缩 CSS 代码;使用 html-webpack-plugin 压缩 html 代码。 开启 gzip 压缩,webpack 中使用 compression-webpack-plugin ,node 作为服务器也要开启,使用 compression。 常用的第三方库使用 CDN 服务,在 webpack 中我们要配置 externals,将比如 React, Vue 这种包不打倒最终生成的文件中。而是采用 CDN 服务。 其它: 使用 http2。因为解析速度快,头部压缩,多路复用,服务器推送静态资源。 使用服务端渲染。 图片压缩。 使用 http 缓存,比如服务端的响应中添加 Cache-Control / Expires 。

手写apply

<!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>手写apply</title>
	</head>
	<body>
		<script>
			Function.prototype.myApply = function (context, args) {
				//这里默认不传就是给window,也可以用es6给参数设置默认参数
				context = context || window
				args = args ? args : []
				//给context新增一个独一无二的属性以免覆盖原有属性
				const key = Symbol()
				context[key] = this
				//通过隐式绑定的方式调用函数
				const result = context[key](...args)
				//删除添加的属性
				delete context[key]
				//返回函数调用的返回值
				return result
			}
			var name = 'geyao'
			var fangfang = {
				name: 'fangfang',

				fang: function () {
					console.log(this.name)
				},

				fun: function () {
                    console.log(this,"this")
					setTimeout(
						function () {
							this.fang()
						}.myApply(this),
						100
					)
				},
			}
			fangfang.fun() //fangfang
		</script>
	</body>
</html>

手写bind

<!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>手写bind</title>
</head>

<body>
  <script>
    Function.prototype.mybind = function (target) {
      //target:改变返回函数执行时的this指向
      var obj = target || window;
      console.log(arguments,"arguments")
      var args = [].slice.call(arguments, 1); //获取bind时传入的绑定实参
      var args1 = [].slice.call(arguments, 0); //获取bind时传入的绑定实参
      console.log(args,"args")
      console.log(args1,"args1")
      var self = this; //要bind的函数
      console.log(self,"self")
      var _fn = function () {
        var _args = [].slice.call(arguments, 0); //新函数执行时传递的实际参数
        console.log(_args,"_args")
        return self.apply(obj, args.concat(_args));
      }
      return _fn
    }
    var name = 'fangfang';
    var obj = {
      name: 'geyao'
    };

    function fn(a, b, c) {
      console.log(a + b + c + this.name);
      return a + b + c + this.name
    };
    fn.mybind(obj,"我的","老婆","是")(); // 我的老婆是geyao
  </script>
</body>

</html>

手写bind2

<!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>手写call</title>
</head>

<body>
  <script>
    Function.prototype.mybind = function (target) {

     
      console.log(arguments,"arguments")
      var args = [].slice.call(arguments, 1); //获取bind时传入的绑定实参
      console.log(args,"args")
      var self = this; //要bind的函数
      console.log(this,"this")
      var temp = function(){};//作为中间函数,用于实现继承
          //target不存在this默认window,当new调用时无需修改this指向
    var obj = this instanceof temp ? this : (target || window);
      var _fn = function () {
        var _args = [].slice.call(arguments, 0); //新函数执行时传递的实际参数
        console.log(_args,"_args")
        console.log(args.concat(_args),"args.concat(_args)")
        return self.apply(obj, args.concat(_args));
      }
         //让中间函数的原型指向,要bind函数的原型
    temp.prototype = self.protoype;
    //让新函数的原型指向中间temp的对象,然后找到要bind函数的原型
    _fn.prototype = new temp();//这样新函数生成的对象的constructor就能找到旧的函数
      return _fn
    }


    var name = 'fangfang';
    var obj = {
      name: 'geyao'
    };

    function fn(a, b, c) {
      console.log(a + b + c + this.name);
      return a + b + c + this.name
    };
    fn.mybind(obj)(1,2,3); // 我的老婆是geyao
  </script>
</body>

</html>

手写call

<!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>手写call</title>
	</head>
	<body>
		<script>
			Function.prototype.myCall = function () {
				//如果是undefined和null 则指向window  不是对象用object转为对象
				let params = Array.from(arguments) //得到所以实参数组
				let _obj = params.splice(0, 1)[0] //获取第一位作为对象,即this指向
				//Symbol()表示独一无二的值
				_obj.fn = this
				var result = obj.fn(...params)
				//删除属性
				delete obj.fn
				return result
			}
			var name = 'fangfang'
			var obj = {
				name: 'geyao',
			}
			function fn(a, b, c) {
				console.log(a + b + c + this.name)
				return a + b + c + this.name
			}
			fn.myCall(obj, '我的', '老婆', '是') // 我的老婆是geyao
		</script>
	</body>
</html>

手写call

<!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>手写call</title>
	</head>
	<body>
		<script>
			Function.prototype.mycall = function (obj) {
				//判断是否为null或者undefined,如果是则默认window;如果传递的参数不是对象用Object转为对象
				obj = obj ? Object(obj) : window
				var args = []

				//注意此处for循环的i是从1开始,因为第1个参数是obj
				for (var i = 1, len = arguments.length; i < len; i++) {
					args.push('arguments' + '[' + i + ']')
				}
				console.log(args, 'args') //[ "arguments[1]", "arguments[2]", "arguments[3]" ]
				//最重要的一步!说明了两个问题:1.mycall内部的this是指向调用者fn函数(对象的);2.Obj.func就是fn函数,
				// obj对象调用了fn函数,因此fn函数内部的this指向obj
				console.log(this, 'this') //function fn(a, b, c)
				obj.fn = this
				// console.log(obj.fn(args),"obj.fn")
				// console.log(eval("obj.fn("+args+")"),"eval")
				var result = eval('obj.fn(' + args + ')')
				delete obj.fn
				console.log(result, 'result') // 我的老婆是geyao
				return result
			}
			var name = 'fangfang'
			var obj = {
				name: 'geyao',
			}

			function fn(a, b, c) {
				console.log(a + b + c + this.name)
				return a + b + c + this.name
			}
			fn.mycall(obj, '我的', '老婆', '是') // 我的老婆是geyao
		</script>
	</body>
</html>

总结

我是歌谣 最好的种树是十年前 其次是现在 加油 歌谣

举报

相关推荐

0 条评论