• 【面筋烧烤手册】20200228


    1、实现五点布局

    在这里插入图片描述

    <div class="box">
      <div class="column">
        <span class="pip"></span>
        <span class="pip"></span>
      </div>
      <div class="column">
        <span class="pip"></span>
      </div>
      <div class="column">
        <span class="pip"></span>
        <span class="pip"></span>
      </div>
    </div>
    
    /* 重点内容 */
    .box{
      display: flex;
      flex-direction: column;
    }
      
    .box .column {
      display: flex;
      justify-content: space-between;
    }
      
    .box .column:nth-of-type(2) {
      justify-content: center;
    }
    
    
    
    body {
      display: flex;
      align-items: center;
      justify-content: center;
      vertical-align: center;
      flex-wrap: wrap;
      align-content: center;
      font-family: 'Open Sans', sans-serif;
      
      background: linear-gradient(top, #222, #333);
    }
    
    .box {
      margin: 16px;
      padding: 4px;
      
      background-color: #e7e7e7;
      width: 104px;
      height: 104px;
      object-fit: contain;
      
      box-shadow:
        inset 0 5px white, 
        inset 0 -5px #bbb,
        inset 5px 0 #d7d7d7, 
        inset -5px 0 #d7d7d7;
      
      border-radius: 10%;
    }
    
    .pip {
      display: block;
      width: 24px;
      height: 24px;
      border-radius: 50%;
      margin: 4px;
    
      background-color: #333;
      box-shadow: inset 0 3px #111, inset 0 -3px #555;
    }
    
    
    
    • 或者换成row弹性,每个元素flex-wrap: wrap; align-content: space-between;,中间的元素align-content: center;
    /* 重点内容 */
        
        .box {
            display: flex;
            flex-direction: row;
        }
        
        .box .column {
            display: flex;
            flex-wrap: wrap;
            align-content: space-between;
        }
        
        .box .column:nth-of-type(2) {
            align-content: center;
        }
        
        body {
            display: flex;
            align-items: center;
            justify-content: center;
            align-content: center;
            background: linear-gradient(top, #222, #333);
        }
    

    2、typeof和instanceof区别

    typeof

    typeof运算符返回一个用来表示表达式的数据类型的字符串。

    typeof一般返回以下几个字符串:

    “number”, “string”,“boolean”,“object”,“function”,“undefined”

    对于Array,Null等特殊对象使用typeof一律返回object,这正是typeof的局限性。

    我们可以使用typeof来判断一个变量是否存在,if(typeof a!= “undefined”), 而不要去使用if(a),因为a不存在(未声明)会报错。

    instanceof

    instanceof用来检测某个对象是不是另一个对象的实例。

    官方的话:该运算发用来测试一个对象在其原型链中是否存在一个构造函数prototype属性

    var a = new Array();
    
    console.log(a instanceof Array);    // 会返回 true
    console.log(a instanceof Object);    // 也会返回 true
    

    因为Array是object 的子类

    function Foo(){}
    Foo.prototype = new Aoo();  // 原型继承
    var foo = new Foo();
    console.log(foo instanceof Foo)  //true
    console.log(foo instanceof Aoo)  //true
    

    instanceof不仅可以判断一层继承关系,也可以判断多层继承关系

    var a = new Array();
    if(a instanceof Object)              // 返回true
    if(window instanceof Object)    // 返回false
    
    typeof(window)  //会得到object
    

    需要注意的是,如果表达式 obj instanceof Foo 返回true,则并不意味着该表达式会永远返回ture,因为Foo.prototype属性的值有可能会改变,改变之后的值很有可能不存在于obj的原型链上,这时原表达式的值就会成为false

    var a = new Array();
    if(a instanceof Object)              // 返回true
    if(window instanceof Object)    // 返回false
    
    typeof(window)  //会得到object
    

    需要注意的是,如果表达式 obj instanceof Foo 返回true,则并不意味着该表达式会永远返回ture,因为Foo.prototype属性的值有可能会改变,改变之后的值很有可能不存在于obj的原型链上,这时原表达式的值就会成为false

    3、状态码 特别是3xx

    1XX 已被接受等待处理

    2XX 成功

    200 请求成功
    204 请求成功⽆资源(OPTIONS的返回状态码)
    206 partial content 范围请求 部分

    3XX 重定向

    301 永久性重定向 已被分配新URL(⾸部会有提示)
    302 临时分配新URL 要改POST为GET
    303 存在另⼀个资源
    304 请访问协商缓存
    307 临时重定向 不改POST
    301 302 303 POST改成GET

    4XX 客户端错误

    400 报⽂语法错误
    401 HTTP请求没通过认证
    403 forbidden 被服务器拒绝
    404 ⽆资源
    405 禁⽌使⽤此⽅法,设置请求头OPTIONS看⽀持什么⽅法

    var Access-Control-Allow-Method = xhr.getResponseHeader('Access-Control-Allow-Method')
    var Access-Control-Allow-Origin = xhr.getResponseHeader('Access-Control-Allow-Origin')
    

    5XX 服务器错误

    500 执⾏请求出错
    502 服务器⾃身正常 但就是访问有问题
    503 暂时停机(可能超负载)⽆法处理请求

    4、 组件中怎么对css进行处理的

    1.提供选项

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    2.函数传参式

    在这里插入图片描述

    在这里插入图片描述

    3.

    在这里插入图片描述

    4.

    在这里插入图片描述

    5、http和https

    HTTPS和HTTP的主要区别

        1、https协议需要到CA申请证书,一般免费证书较少,因而需要一定费用。
    
        2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl/tls加密传输协议。
    
        3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
    
        4、http的连接很简单,是无状态的;HTTPS协议是由SSL/TLS+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
    	
    	5、https在握手时多个步骤,并且后面还有认证环节,比http时间花得多
    

    7、浏览器缓存

    8、跨域方法

    9、JS判断为数组的方式

    链接

    1.instanceof

    在这里插入图片描述

    手写instanceof

    function myInstanceof(letf, right){
    	let proto = Object.getPrototypeOf(left),
    		prototype = right.prototype;
    	while(true){
    		if(!proto) return false;
    		if(proto === prototype) return true;
    		proto = Object.getPrototypeOf(proto);
    	}
    }
    

    2.Object.prototype.toString.call

    Object.prototype.toString.call(variable).indexOf('Array') !== -1;
    //或者
    Object.prototype.toString.call(variable).slice(8, -1) === 'Array';
    
    调用toString时会将this对象的[[class]]属性值拿到,而这个属性值就是该对象的真实类型。
    
    又因为call能够显示的修改this指针的对象,所以用call将Object内部的this对象指向我们要检测的变量自身。
    
    从而再通过toString拿到变量的[[class]]值。
    

    3.原型prototype + isPrototypeOf()方法

    Array.prototype.isPrototypeOf(variable) 
    
    isPrototypeOf() 函数 : 用于指示对象是否存在于一个对象的原型链中。如果存在返回true,反之返回false。该方法属Object对象,由于所有的对象都继承了Object的对象实例,因此几乎所有的实例对象都可以使用该方法。
    

    原型复习

    在这里插入图片描述

    4.variable.constructor.toString()

    variable.constructor.toString().indexOf("Array")== -1
    
    • 但是有个问题就是 constructor如果被改了,就会不对
      在这里插入图片描述

    5.Array.isArray(variable)

    10、JS将类数组转换成数组的方法

    1.slice()

    最经典的方法,使用Array的slice方法,此方法如果不传参数的话会返回原数组的一个拷贝,因此可以用此方法转换类数组到数组;
    
    // 创建一个类数组对象
    var alo = {0:"a", 1:"b",2:"c", length:3};
    
    // 转化
    var arr = Array.prototype.slice.call(alo);
    
    console.log(
        Array.isArray(alo) // false
    )
    
    console.log(
        Array.isArray(arr) // true
    )
    
    console.log(alo); // { '0': 'a', '1': 'b', '2': 'c', length: 3 }
    console.log(arr); // [ 'a', 'b', 'c' ]
    

    2. Array.from()

    ES6的方法,只要有length属性的对象,都可以应用此方法转换成数组。

    let arrayLike = {
        '0': 'a',
        '1': 'b',
        '2': 'c',
        length: 3
    };
    
    // ES5的写法
    var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
    
    // ES6的写法
    let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
    

    3. 扩展运算符

    ES6中的扩展运算符…也能将某些数据结构转换成数组,这种数据结构必须有便利器接口。

    扩展运算符背后调用的是遍历器接口(Symbol.iterator),如果一个对象没有部署这个接口,就无法转换。

    var args = [...arguments];
    

    4. $.makeArray()

    jQuery的此方法可以将类数组对象转化为真正的数组

    var arr = $.makeArray(arguments);
    

    11、AMD与CMD和COMMONJS

    链接

    commonjs

    //定义一个module.js文件
    var A = function() {
        console.log('我是定义的模块');
    }
    //导出这个模块
    //1.第一种返回方式 module.exports = A; 
    //2.第二种返回方式 module.exports.test = A
    //3.第三种返回方式 exports.test = A;
    exports.test = A;
    
    
    
    //再写一个test.js文件,去调用刚才定义好的模块,这两个文件在同一个目录下
    var module = require("./module");  //加载这个模块
    
    //调用这个模块,不同的返回方式用不同的方式调用
    //1.第一种调用方式 module();
    //2.第二种调用方式 module.test();
    //3.第三种调用方式 module.test();
    module.test();
    
    
    //接下来我们去执行这个文件,前提是你本地要安装node.js,不多说了,自己百度安装。
    //首先打开cmd, cd到这两个文件所在的目录下,执行: node test.js
    node test.js
    //输出结果:我是定义的模块
    

    AMD

    //编写一个module1.js文件
    //定义独立的模块
    define({
        methodA: function() {
            console.log('我是module1的methodA');    
        },
        methodB: function() {
            console.log('我是module1的methodB');    
        }
    });
    
    
    
    //编写一个module2.js文件
    //另一种定义独立模块的方式
    define(function () {
        return {
            methodA: function() {
                console.log('我是module2的methodA');    
            },
            methodB: function() {
                console.log('我是module2的methodB');    
            }
        };
    });
    
    
    
    //编写一个module3.js文件
    //定义非独立的模块(这个模块依赖其他模块)
    define(['module1', 'module2'], function(m1, m2) {
        return {
            methodC: function() {
                m1.methodA();
                m2.methodB();
            }
        };
    
    });
    
    
    
    //再定义一个main.js,去加载这些个模块
    require(['module3'], function(m3){
        m3.methodC();
    });
    
    
    //我们在一个html文件中去通过RequireJS加载这个main.js
    //等号右边的main指的main.js
    <script data-main="main" src="require.js"></script>
    
    //浏览器控制台输出结果
    我是module1的methodA
    我是module2的methodB
    

    AMD和CMD的区别:

    1. 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。CMD 推崇 as lazy as possible(尽可能的懒加载,也称为延迟加载,即在需要的时候才加载)。

    2. CMD 推崇依赖就近,AMD 推崇依赖前置。
      虽然 AMD 也支持 CMD 的写法,同时还支持将 require 作为依赖项传递,但 RequireJS 的作者默认是最喜欢上面的写法,也是官方文档里默认的模块定义写法。看代码:

    // CMD
    define(function(require, exports, module) {
        var a = require('./a');
        a.doSomething();
        // 此处略去 100 行
        var b = require('./b');   // 依赖可以就近书写
        b.doSomething();
        // ... 
    })
    
    // AMD 默认推荐的是
    define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好
        a.doSomething();
        // 此处略去 100 行
        b.doSomething();
        //...
    }) 
    

    12、【手撕】手写深拷贝

    /* 
    深度克隆
    1). 大众乞丐版
        问题1: 函数属性会丢失
        问题2: 循环引用会出错
    2). 面试基础版本
        解决问题1: 函数属性还没丢失
    3). 面试加强版本
        解决问题2: 循环引用正常
    4). 面试加强版本2(优化遍历性能)
        数组: while | for | forEach() 优于 for-in | keys()&forEach() 
        对象: for-in 与 keys()&forEach() 差不多
    */
    /* 
    1). 大众乞丐版
      问题1: 函数属性会丢失
      问题2: 循环引用会出错
    */
    export function deepClone1(target) {
      return JSON.parse(JSON.stringify(target))
    }
    
    /* 
    获取数据的类型字符串名
    */
    function getType(data) {
      return Object.prototype.toString.call(data).slice(8, -1)
    }
    
    /*
    2). 面试基础版本
      解决问题1: 函数属性还没丢失
    */
    export function deepClone2(target) {
      const type = getType(target)
    
      if (type==='Object' || type==='Array') {
        const cloneTarget = type === 'Array' ? [] : {}
        for (const key in target) {
          if (target.hasOwnProperty(key)) {
            cloneTarget[key] = deepClone2(target[key])
          }
        }
        return cloneTarget
      } else {
        return target
      }
    }
    
    /* 
    3). 面试加强版本
      解决问题2: 循环引用正常
    */
    export function deepClone3(target, map = new Map()) {
      const type = getType(target)
      if (type==='Object' || type==='Array') {
        let cloneTarget = map.get(target)
        if (cloneTarget) {
          return cloneTarget
        }
        cloneTarget = type==='Array' ? [] : {}
        map.set(target, cloneTarget)
        for (const key in target) {
          if (target.hasOwnProperty(key)) {
            cloneTarget[key] = deepClone3(target[key], map)
          }
        }
        return cloneTarget
      } else {
        return target
      }
    }
    
    /* 
    4). 面试加强版本2(优化遍历性能)
        数组: while | for | forEach() 优于 for-in | keys()&forEach() 
        对象: for-in 与 keys()&forEach() 差不多
    */
    export function deepClone4(target, map = new Map()) {
      const type = getType(target)
      if (type==='Object' || type==='Array') {
        let cloneTarget = map.get(target)
        if (cloneTarget) {
          return cloneTarget
        }
    
        if (type==='Array') {
          cloneTarget = []
          map.set(target, cloneTarget)
          target.forEach((item, index) => {
            cloneTarget[index] = deepClone4(item, map)
          })
        } else {
          cloneTarget = {}
          map.set(target, cloneTarget)
          Object.keys(target).forEach(key => {
            cloneTarget[key] = deepClone4(target[key], map)
          })
        }
    
        return cloneTarget
      } else {
        return target
      }
    }
    

    13、【手撕】具有最大和的连续子数组

    给定一个整数数组 nums ,给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最
    少包含一个元素),返回其最大和。
    示例 1: 输入:nums = [-2,1,-3,4,-1,2,1,-5,4] 输出:6 解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。

    • c语言实现
    #define _CRT_SECURE_NO_WARNINGS 
    #include <stdio.h>
    #include <stdlib.h>
    int maxSubArray(int* nums, int numsSize) {
    	int sum = 0;
    	int max = nums[0];
    	for (int i = 0; i<numsSize; i++)
    	{
    		if (sum>0)
    		{
    			sum += nums[i];//只有sum大于0   加上一个数才有可能继续增大
    		}
    		if (sum <= 0)
    		{
    			sum = nums[i];//sum小于0   就让它等于第i位
    		}
    		if (sum>max)
    		{
    			max = sum;
    		}
    	}
    	return max;
    }
    int main()
    {
    	int num[] = { -2, 1, -3, 4, -1, 2, 1, -5, 4 };
    	int len = sizeof(num) / sizeof(int);
    	int a = maxSubArray(num, len);
    	printf("%d
    ", a);
    	system("pause");
    	return 0;
    }
    
    
    
    // 给定一个整数数组 nums ,给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最
    // 少包含一个元素),返回其最大和。 
    // 示例 1: 输入:nums = [-2,1,-3,4,-1,2,1,-5,4] 输出:6 解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。 
    
    function subArrayWithMaxSum(arr) {
        let sum = 0,
            max = arr[0];
        arr.forEach(i => {
            (sum > 0) && (sum += i);
            (sum <= 0) && (sum = i);
            (sum > max) && (max = sum);
            console.log("   i:" + i + "    sum:" + sum + "    max:" + max);
        });
        return max;
    }
    
    /*
     *以下是测试代码 
     */
    console.log(subArrayWithMaxSum([-2, 1, -3, 4, -1, 2, 1, -5, 4]))
        //    i:-2    sum:-2    max:-2
        //    i:1    sum:1    max:1
        //    i:-3    sum:-3    max:1
        //    i:4    sum:4    max:4
        //    i:-1    sum:3    max:4
        //    i:2    sum:5    max:5
        //    i:1    sum:6    max:6
        //    i:-5    sum:1    max:6
        //    i:4    sum:5    max:6
    

    14、输出题

    let obj = {
        name: "bytedance",
        fun: function(){
            console.log(this.name,this);
        }
    }
    let a = obj.fun;
    a(); // Window 和 Window对象
    obj.fun();  // bytedance 和 obj对象
    
    
    for (var i = 0; i < 5; i++) {
        setTimeout(function() {
            console.log(new Date(), i);
        }, 1000);
    }
    console.log(new Date(), i);
    // 先有个5 过一秒再 5 5 5 5 5
    

    15.【手撕】bind call apply

    // call函数实现
    Function.prototype.myCall = function(context) {
      // 判断调用对象
      if (typeof this !== "function") {
        console.error("type error");
      }
    
      // 获取参数
      let args = [...arguments].slice(1),
        result = null;
    
      // 判断 context 是否传入,如果未传入则设置为 window
      context = context || window;
    
      // 将调用函数设为对象的方法
      context.fn = this;
    
      // 调用函数
      result = context.fn(...args);
    
      // 将属性删除
      delete context.fn;
    
      return result;
    };
    
    // apply 函数实现
    
    Function.prototype.myApply = function(context) {
      // 判断调用对象是否为函数
      if (typeof this !== "function") {
        throw new TypeError("Error");
      }
    
      let result = null;
    
      // 判断 context 是否存在,如果未传入则为 window
      context = context || window;
    
      // 将函数设为对象的方法
      context.fn = this;
    
      // 调用方法
      if (arguments[1]) {
        result = context.fn(...arguments[1]);
      } else {
        result = context.fn();
      }
    
      // 将属性删除
      delete context.fn;
    
      return result;
    };
    
    // bind 函数实现
    Function.prototype.myBind = function(context) {
      // 判断调用对象是否为函数
      if (typeof this !== "function") {
        throw new TypeError("Error");
      }
    
      // 获取参数
      var args = [...arguments].slice(1),
        fn = this;
    
      return function Fn() {
        // 根据调用方式,传入不同绑定值
        return fn.apply(
          this instanceof Fn ? this : context,
          args.concat(...arguments)
        );
      };
    };
    

    回答:

    call 函数的实现步骤:

    • 1.判断调用对象是否为函数,即使我们是定义在函数的原型上的,但是可能出现使用 call 等方式调用的情况。
    • 2.判断传入上下文对象是否存在,如果不存在,则设置为 window 。
    • 3.处理传入的参数,截取第一个参数后的所有参数。
    • 4.将函数作为上下文对象的一个属性。
    • 5.使用上下文对象来调用这个方法,并保存返回结果。
    • 6.删除刚才新增的属性。
    • 7.返回结果。

    apply 函数的实现步骤:

    • 1.判断调用对象是否为函数,即使我们是定义在函数的原型上的,但是可能出现使用 call 等方式调用的情况。
    • 2.判断传入上下文对象是否存在,如果不存在,则设置为 window 。
    • 3.将函数作为上下文对象的一个属性。
    • 4.判断参数值是否传入
    • 4.使用上下文对象来调用这个方法,并保存返回结果。
    • 5.删除刚才新增的属性
    • 6.返回结果

    bind 函数的实现步骤:

    • 1.判断调用对象是否为函数,即使我们是定义在函数的原型上的,但是可能出现使用 call 等方式调用的情况。
    • 2.保存当前函数的引用,获取其余传入参数值。
    • 3.创建一个函数返回
    • 4.函数内部使用 apply 来绑定函数调用,需要判断函数作为构造函数的情况,这个时候需要传入当前函数的 this 给 apply 调用,其余情况都传入指定的上下文对象。
  • 相关阅读:
    如何一次插入多条记录的SQL语句
    oracle 创建联合主键语句
    02-36 支持向量回归
    245 第三篇:Django-路由控制
    244 第二篇:Django简介
    243 第一篇:自定义Web框架
    242 第一篇:Http协议详细介绍
    02-34 非线性支持向量机(鸢尾花分类)+自定义数据分类
    241 第一篇:web应用
    240 vue学习【第6篇】:vue之导入Bootstrap
  • 原文地址:https://www.cnblogs.com/SiriusZHT/p/14521324.html
Copyright © 2020-2023  润新知