JS高级. 06 缓存、分析解决递归斐波那契数列、jQuery缓存、沙箱、函数的四种调用方式、call和apply修改函数调用方法

时间:2024-06-24 23:33:32

缓存

  1. cache
  2. 作用就是将一些常用的数据存储起来
  3. 提升性能
  4. cdn
 //-----------------分析解决递归斐波那契数列
<script> //定义一个缓存数组,存储已经计算出来的斐波那契数
//1.计算的步骤
//1.先从cache数组中去取想要获取的数字
//2.如果获取到了,直接使用
//3.如果没有获取到,就去计算,计算完之后,把计算结果存入cache,然后将结果返回 // var cache = [];
//
// function fib(n){
// //1.从cache中获取数据
// if(cache[n] !== undefined){
// //如果缓存中有 直接返回
// return cache[n];
// }
// //如果缓存中没有 就计算
// if(n <= 2){
// //把计算结果存入数组
// cache[n] = 1;
// return 1;
// }
// var temp = fib(n - 1) + fib(n - 2);
// //把计算结果存入数组
// cache[n] = temp;
// return temp;
// }
//
// console.log(fib(6)); //
// var count =0 ;
// function createFib(){
// var cache = [];
// function fib(n){
// count ++;
// //1.从cache中获取数据
// if(cache[n] !== undefined){
// //如果缓存中有 直接返回
// return cache[n];
// }
// //如果缓存中没有 就计算
// if(n <= 2){
// //把计算结果存入数组
// cache[n] = 1;
// return 1;
// }
// var temp = fib(n - 1) + fib(n - 2);
// //把计算结果存入数组
// cache[n] = temp;
// return temp;
// }
// return fib;
// } // 把下一个知识点应用进来,创建缓存容器 // function createCache(){
// var cache = {};
// return function (key, value) {
// //如果传了值,就说名是设置值
// if(value !== undefined){
// cache[key] = value;
// return cache[key];
// }
// //如果没有传值,只穿了键,那就是获取值
// else{
// return cache[key];
// }
// }
// } // 缓存容器
function createCache(){
var cache = {};
return function (key, value){
if(value != undefined){
cache[key] = value;
return cache[key];
}
else{
return cache[key]; // 不是赋值 就是取值
}
}
} var count =0 ;
function createFib(){
var fibCache = createCache();
function fib(n){
count ++;
//1.从cache中获取数据
if(fibCache(n) !== undefined){
//如果缓存中有 直接返回
return fibCache(n) ;
}
//如果缓存中没有 就计算
if(n <= 2){
//把计算结果存入数组
fibCache(n , 1) ;
return 1;
}
var temp = fib(n - 1) + fib(n - 2);
//把计算结果存入数组
fibCache(n, temp) ;
return temp;
} return fib;
} var fib = createFib();
// console.log(fib(6));
fib(5);
console.log(count);
count = 0;
fib(6);
console.log(count);
count = 0;
fib(20);
console.log(count);
count = 0;
fib(21);
console.log(count);
count = 0; </script>

jQuery缓存实现的分析

JS高级. 06 缓存、分析解决递归斐波那契数列、jQuery缓存、沙箱、函数的四种调用方式、call和apply修改函数调用方法
    <script>
//eleCache
//typeCache
//classCache
//eventCache function createCache(){
//cache对象中以键值对的形式存储我们的缓存数据
var cache = {};
//index数组中该存储键,这个键是有顺序,可以方便我们做超出容量的处理
var index = [];
return function (key, value) {
//如果传了值,就说名是设置值
if(value !== undefined){
//将数据存入cache对象,做缓存
cache[key] = value;
//将键存入index数组中,以和cache中的数据进行对应
index.push(key); //判断缓存中的数据数量是不是超出了限制
if(index.length >= 40){
//如果超出了限制
//删除掉最早存储缓存的数据
//最早存入缓存的数据的键是在index数组的第一位
//使用数组的shift方法可以获取并删除掉数组的第一个元素
var tempKey = index.shift();
//获取到最早加入缓存的这个数据的键,可以使用它将数据从缓存各种删除
delete cache[tempKey];
}
}
//如果没有传值,只穿了键,那就是获取值
else{
return cache[key];
}
return cache[key];
}
} var eleCache = createCache();
eleCache("name","高金彪");
console.log(eleCache("name"));
var typeCche = createCache();
</script>

jQuery缓存的分析

<script>
function createCache() {
var keys = [];
function cache( key, value ) {
// 使用(key + " ") 是为了避免和原生(本地)的原型中的属性冲突
if ( keys.push( key + " " ) > 3 ) {
// 只保留最新存入的数据
delete cache[ keys.shift() ];
}
// 1 给 cache 赋值
// 2 把值返回
return (cache[ key + " " ] = value);
}
return cache;
} var typeCache = createCache();
typeCache("monitor");
console.log(typeCache["monitor" + " "]); typeCache("monitor","张学友");
console.log(typeCache["monitor" + " "]); typeCache("monitor2","刘德华");
console.log(typeCache["monitor2" + " "]); typeCache("monitor3","彭于晏");
console.log(typeCache["monitor3 "]); // console.log(typeCache["monitor "]); </script>

沙箱

  1. 与外界隔绝的一个环境,外界无法修改内部的数据
  2. 沙箱基本模型

    a)  沙箱中将所有变量的定义放最上面

    b)  中间放一些逻辑代码

    c)

(function(){
//变量定义
//逻辑代码
//如果需要,向window对象添加成员,以暴露接口
})()
  1. 如果需要在外加暴力一些属性或者方法,就可以将这些属性或者方法加到window全局对象上
  2. 但是这个window全局对象不可以直接引用,因为引用会破坏沙箱原则
  3. 所以我们选择使用传参的形式将window对象传入沙箱内
  4. 一般应用在书写第三方框架或者为第三方框架书写插件或者书写功能独立的一些组件

沙箱的优势

  1. 杀星模式使用的是IIFE,不会在外界报篓任何全局变量,也不会找茬代码污染
  2. 沙箱中的所有数据,都和外界隔离的,外界无法对其进行修改
  3. 函数可以创建作用域, 上级作用域无法直接访问下级作用域

沙箱实现原理

  函数可以创建作用域, 上级作用域无法直接访问下级作用域

第三方框架
插件
独立的组件

函数的四种调用模式

函数模式    

  this指向window全局对象

方法模式

  this指向调用这个方法的对象

var obj = {
name:'jack',
sayHello: function () {
console.log('hello');
}
}
obj.sayHello();

构造函数模式  

    this  使用new创建出来的对象

    new Obj()

简单工厂模式的构造函数创建出来的对象和工厂函数无关

function Person(name, age){

        var o={
name:name,
age:age
}
return o;
}
var p = Person('jack',20);
console.log(p); // P 是一个 Object对象,和构造函数Person()无关

  寄生式构造函数

a)    function fun(name, age) {
var o = {
name: name,
age: age
}
return o;
}
var obj = new fun('jack', 20); //创建出来的是Object对象,和构造函数无关

  简单工厂模式的构造函数,实际上调用模式是 函数模式 调用

上下文模式 

     var name = "莱昂纳多·自强·郭";
function sayHello(a, b) {
console.log(this.name + "吃了"+ (a * b) + "个馒头");
} sayHello(); // 莱昂纳多·自强·郭吃了NaN个馒头 var obj = {
name:"尼古拉斯·电饭·锅"
} var arr= []
arr.push();
arr.push();
sayHello.apply(obj,arr); // 尼古拉斯·电饭·锅吃了NaN个馒头
     sayHello.call(obj, 1, 2); // 尼古拉斯·电饭·锅吃了2个馒头

1.  左值(等号左边)  右值(等号右边)

a)  左值被赋值
b)  右值不能被赋值,
2.  上下文调用模式中,可以修改this的值,也就是可以修改函数调用方法
3.  使用如下方法可以修改上下文,也就是this的值
  a)  apply:函数.apply(this修改成的那个对象,[可传可不传])//传数组
  b)  call:函数.call(this修改成的那个对象,[value1], [value2], ...[valueN]);
  c)  定义在Function.prototype里
  d)  数组可以点出来任何属性不报错
//案例:将传入的参数打印,参数之间用-相互连接
function foo(){
// return arguments.join("-"); // 是错误的
//伪数组不具有join方法,所以这个时候就要考虑去借用一下数组的join方法
var str = Array.prototype.join.apply ( arguments, ["-"]);
// var str2 = [].join.apply( arguments ,["-"]);
return str ;
} var str = foo(1,2,"abc","sofa",99)
console.log(str);// 1-2-abc-sofa-99
4.  call和apply的区别
  a)  第一个参数都是要把this修改成对象
  b)  当函数需要参数的时候,那么apply用数组进行传值
  c)  call用单个参数传值
  d)  apply和call方法第一个传入参数是null的时候都表示为函数调用模式
    1.  也就是将this指向window
5.  array.prototype === [];两个书写方式表达的意思相同
6.  api文档语句中[],的内容表示可有可无
7.  undefined*undefined = NaN
//案例:求一个数组中的最大值
var arr = [9, 1, 4, 10, 7, 22, 8];
//Math.max
// Math.max(1,2,34,5); //apply方法的第二个参数 是一个数组
// 在调用的时候,会将数组中的每一个元素拿出来,作为形参,挨个传递给函数 //apply方法和call方法第一个参数传递null的时候,都表示为函数调用模式
//也就是将this指向window
var max = Math.max.apply( null ,arr);
console.log ( max ); //22
window.onload = function () {
//案例:给页面上所有的 div 和 p 标签添加背景色
var divs = document.getElementsByTagName("div");
var ps = document.getElementsByTagName("p"); var arr = [];
//little tip: push方法可以传多个参数
//arr.push(1,2,3,4,4,5) arr.push.apply(arr,divs);
arr.push.apply(arr,ps); //如果使用arr.push()直接把divs传进来
//那么相当于在arr中的第一个元素中存储了一个divs数组
//但是我们需要把divs中的每一个元素单独的存入arr中
//所以需要调用push方法的如下形式 push(1,2,4,4,5)
//要实现这个形式的调用,就用到了apply方法的第二个参数的特性
//在调用的时候,将第二个参数的数组,拆成每一个元素以(a,b,c,d,e,f,g) 传入函数 //相当于 arr.push(divs[0],divs[1],divs[..])
// arr.push(divs) for (var k = 0; k < arr.length; k++) {
var ele = arr[k];
ele.style.backgroundColor = "yellow";
} // for (var i = 0; i < divs.length; i++) {
// var div = divs[i];
// div.style.backgroundColor = "#ccc";
// }
//
// for (var j = 0; j < ps.length; j++) {
// var p = ps[j];
// p.style.backgroundColor = "#ccc";
// }
}