Giter Site home page Giter Site logo

blog-node's Introduction

👋 Hey there

  • 🏢 I'm currently working at MEITU
  • 🚀 I use daily: JavaScript Git VS Code
  • 💻 I work using: Vue Sass GitHub GitLab
  • 🔥 I also use and work: HTML5 CSS3 TypeScript
  • 📚 Learning all about: Node.JS Express.JS Graphql MongoDB

blog-node's People

Contributors

hongxinzz avatar

Watchers

 avatar

blog-node's Issues

封装一个Cookie

// Cookie 对象
Cookie = {

    /**
    * cookie 设置方法
    * @param {String} name 属性名
    * @param {String} value 属性值
    */
    set: function (name, value) {
        document.cookie = encodeURIComponent(name) + '='
            + encodeURIComponent(value);
    },

    /**
    * cookie 获取方法
    * @param {String} name 属性名
    * @return {String} 返回对应的属性值
    */
    get: function (name) {
        var nameStr = name + "=";
        var decodedCookie = decodeURIComponent(document.cookie);
        var ca = decodedCookie.split(';');
        for (var i = 0; i < ca.length; i++) {
            var c = ca[i];
            while (c.charAt(0) == ' ') {
                c = c.substring(1);
            }
            if (c.indexOf(nameStr) == 0) {
                return c.substring(nameStr.length, c.length);
            }
        }
        return "";
    },

    /**
    * cookie 删除方法
    * @param {String} name 属性名
    */
    remove: function (name) {
        document.cookie = encodeURIComponent(name) + '='
            + '' + ';Expires=' + new Date(0);
    }

}

JavaScript 预编译 AO GO 暗示全局变量

浏览器编译过程:

检查通篇的语法错误

解释一行 执行一行

<script>
    console.log(a;)//Uncaught SyntaxError: missing ) after argument list
    console.log(a) //Uncaught ReferenceError: a is not defined
</script>

声明提升:

函数声明整体提升
变量只有生命提升,赋值不提升

test()
function test(){
    console.log(1) //1
}

console.log(a)// undefined                var a;
var a = 1;                                   =>      console.log(a)
                                                             a = 1;

抛出一个问题:下面输出什么?

console.log(a); 
function a (a){
    var a = 10;
    var a = function(){
        
    }
}
var a = 1;

//ƒ a (a){
    var a = 10;
    var a = function(){
        
    }
}

变量的声明:

在声明一个变量时不管有没有var 都会默认挂载在window身上

var a = 1;                         window = { a:1,b:2}
b =2;                   =>      console.log(a,window.b)// 1,2

函数体内的预编译:

AO Activation Object 活跃对象,函数上下文

可以理解成一个AO对象并且存储了函数体内执行和未执行的变化

function test(a){
    console.log(a); //function a(){} 函数提升
    var a = 1;
    console.log(a);//1 赋值
    function a(){}
    console.log(a) //1 赋值
    var b = function(){}
    console.log(b) //function(){} 函数提升
    function d(){}
}
//函数未运行时 预编译
//AO = {
//    a: 变量提升 undefined -> 形参 2 -> 函数体 function a(){}
//    b: 变量提升 undefined
//    d: 变量提升 function d(){}
// }
test(2)
//运行函数
//AO = {
//    a: 变量提升 undefined -> 形参 2 -> 函数体 function a(){} -> 赋值 1 
//    b: 变量提升 undefined-> 赋值 function(){}
//    d: 函数提升 function d(){}
// }

//总结:
//    1.寻找形参和变量声明
//    2.实参赋值给形参
//    3.找函数声明,进行赋值操作
//    4.执行



//再试试一题
   function test2(a,b){
        console.log(a);//1  形参赋值
        c = 0;
        var c;
        a = 5;
        b = 6;
        console.log(b);//6 赋值
        function b(){};
        function d(){};
        console.log(b)//6 赋值
    }

    test2(1)
// AO = {
//    a: 变量提升 undefined -> 形参 1 -> 赋值 5
//    b: 函数提升 function b(){} -> 赋值6;
//    d: 变量提升 function d(){}
//    c: not defined  -> 赋值 0
//    d: function d(){}
// }

2.GO Global Object 全局上下文

相对于AO 少了一个参数的操作

console.log(a) //function a(){}
var a = 1;
function a(){}
console.log(a)//1

//GO = {
//    a:undefined ->functiona a(){} -> 1
//}

//总结:
//    1.找变量声明
//    2.找函数声明
//    3.赋值

实战:

//AO GO 结合实战
function test(){
    console.log(b); //undefind
    if(a){ //函数执行时 a为undefined,undefined为false
        var b = 2;
    }
    c = 3; 
    console.log(c) //3
}
var a;
test();
a = 1;
console.log(a)// 1

// // 未执行AO GO 分析
// AO = {
//     b:undefined //为什么会直接undefined 因为在预编译阶段var变量该提升还是提升 当函数执行时才会去执行if语句
// }
// GO = {
//     a:undefined,
//     test:function test(){},
//     c:3 //在函数体内不是通过 var声明都会挂载在window身上
// }

// 执行AO GO 分析
// AO = {
//     b:undefined 
// }
// GO = {
//     a:undefined -> 1,
//     test:function test(){},
//     c:3 
// }

html预处理(sass)

变量

/*变量*/
$width:100px;
$color:blue;

.demo
{
    width: $width;
    height: $width/2;
    background: $color;
}

编译后:

.demo
 {
    width: 100px;
    height: 50px;
    background: blue; 
}

嵌套

.box1{
    width:100px;
    height:100px;
    background:blue;
    .box2{
        wid:100px;
        height:100px;
        background:red;
    }
}

编译后:

.box1{
    width:100px;
    height:100px;
    background:blue;
}
.box1 .box2{
    wid:100px;
    height:100px;
    background:red;
}

mixin 混入

类似于函数传参 @mixin定义 @incldue 引用

@mixin demo($size:100px,$color:lightblue){
    width: $size;
    height: $size;
    background: $color;
}
.box1{
    @include demo();
}

.box2{
    @include demo(150px);
}

.box3{
    @include demo(200px,lightgreen);
}

编译为:

.box1 {
    width: 100px;
    height: 100px;
    background: lightblue;
}

.box2 {
    width: 150px;
    height: 150px;
    background: lightblue;
}

.box3 {
    width: 200px;
    height: 200px;
    background: lightgreen;
}

扩展/继承

通过关键字 @extend

.demo
{
    background: blue;
    border: 1px solid lightblue;
}

.box{
    @extend .demo;
    background: green;
}

.error
{
    @extend .demo;
    border: 2px solid red;
}

编译为:

.demo,
.success,
.error {
    background: blue;
    border: 1px solid lightblue;
}

.success {
    background: green;
}

.error {
    border: 2px solid red;
}

函数式

Sass中自带了很多颜色参数

$pcolor: #ed4040;
.cls71 a {
    color: $pcolor;
    &:hover {
        background: darken($pcolor,15%);
        /*变暗15%*/
        color: lighten($pcolor,5%);
        /*变亮5%*/
    }

流程控制

sass中和js一样也拥有流程控制语句,如if,for,each,while,指令,函数等。

$blur: lightblue;
@for $i from 1 through 10 {
    .font-#{$i} {
        /*计算字体大小*/
        font-size: 12px+$i*2px;
        /*颜色变暗*/
        color: darken($blur,$i*2);
        /*如果i是3的倍数,则下划线*/
        @if $i%3==0 {
            text-decoration: underline;
        }
    }
}

编译后:

.font-1 {
  font-size: 14px;
  color: #a5d4e4; }

.font-2 {
  font-size: 16px;
  color: #9dd1e1; }

.font-3 {
  font-size: 18px;
  color: #96cddf;
  text-decoration: underline; }

.font-4 {
  font-size: 20px;
  color: #8ec9dc; }

.font-5 {
  font-size: 22px;
  color: #86c5da; }

.font-6 {
  font-size: 24px;
  color: #7ec2d8;
  text-decoration: underline; }

.font-7 {
  font-size: 26px;
  color: #76bed5; }

.font-8 {
  font-size: 28px;
  color: #6ebad3; }

.font-9 {
  font-size: 30px;
  color: #67b7d1;
  text-decoration: underline; }

.font-10 {
  font-size: 32px;
  color: #5fb3ce; }

JS防抖和节流

函数防抖(debounce):当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时.

function debounce(fn, wait) {
    var timeout = null;
    return function() {
        if(timeout !== null) 
                clearTimeout(timeout);
        timeout = setTimeout(fn, wait);
    }
}
// 处理函数
function handle() {
    console.log(Math.random()); 
}
// 滚动事件
window.addEventListener('scroll', debounce(handle, 1000));

函数节流(throttle):当持续触发事件时,保证一定时间段内只调用一次事件处理函数。节流通俗解释就比如我们水龙头放水,阀门一打开,水哗哗的往下流,秉着勤俭节约的优良传统美德,我们要把水龙头关小点,最好是如我们心意按照一定规律在某个时间间隔内一滴一滴的往下滴。

function throttle (fn,time){
  var fristTime =  Date.now();
  return function(){
    var self = this,
        args = arguments;
    var nowTime =  Date.now();
    if(nowTime - fristTime > time){
      fn.apply(self, args);
      fristTime = Date.now();
    }
  }
}
function handle() {
  console.log(Math.random());
}
window.addEventListener('scroll', throttle(handle, 1000));

Object.defineProperty(Vue双向绑定)

对象中的defineProperty

defineProperty接收三个参数:
属性所在的对象、属性的名字和一个描述符对象;

var person  = {};
Obeject.defineProperty(person,'name',{
    value:"zhuo"
})

描述对象有三个参数 和 一个 value值

configurableenumerablewritablevalue

//writable:boolen; true时可以修改value值,否则value只为只读状态

var person = {};
Object.defineProperty(person, "name", {
    writable: false,
    value: "zhuo"
});
console.log(person.name); //"zhuo" 
person.name = "Greg"; 
console.log(person.name); //"zhuo"

//configurable true时可以操作value false为不可操作value

var person = {};
Object.defineProperty(person, "name", {
    configurable: true,
    value: "zhuo"
});
delete person.name
console.log(person); // {}

//enumerable   false时对象不可被列举,true为可被列举
var person = {};
Object.defineProperty(person, "name", {
    enumerable:true,
    value: "zhuo"
});
for(let key in person){
    console.log(key) //zhuo
}

内置方法 get set

当定义get 或者set时,defineProperty不能包含writablevalue

var person = {};
Object.defineProperty(person, "name", {
    enumerable:true,
    configurable:true,
    get(){
        //获取person.name的时候会调用Get方法
        return 'zhuo'
    },
    set(val){
        //赋值的时候会调用set方法
        console.log(val)
    }
});
console.log(person.name) //zhuo
person.name = 'zhuo2'// zhuo2

一个面试引起的布局方式

题目:
假设高度已知,请写出三蓝布局,其中左右栏分别为300px,中间自适应。

一个很经典的布局面试题。一共有4中比较流行的布局方案。(不使用table)

第一种 Float布局

 <!-- float方法 -->
        <section class="layout float">
             <style>
                .float-left{
                    float: left;
                    width: 300px;
                    background: yellow
                }
                .float-right{
                    float: right;
                    width: 300px;
                    background: red
                }
                .antuo-center{
                    background: blue;
                }
            </style>
            <div class="float-left"></div>
            <div class="float-right"></div>
            <div class="antuo-center">
                <h1>我是浮动方案</h1>
            </div>
         </section>

第二种 定位布局

 <!-- 定位方法 -->
        <section class="layout position">
            <style>
                .position-left{
                    position: absolute;
                    left: 0;
                    width: 300px;
                    background: yellow
                }
                .position-right{
                    position: absolute;
                    right: 0;
                    width: 300px;
                    background: red
                }
                .position-center{
                    position: absolute;
                    left: 300px;
                    right: 300px;
                    background: blue;
                }
            </style>
            <div class="position-left"></div>
            <div class="position-right"></div>
            <div class="position-center">
                <h1>我是定位方案</h1>
             </div>
        </section>

第三种 Flex布局

 <!-- flex方法 -->
        <section class="layout flex">
            <style>
                .flex{
                    display: flex;
                    margin-top: 300px;
                }
                .flex-left{
                    width: 300px;
                    background: yellow
                }
                .flex-right{
                
                    width: 300px;
                    background: red
                }
                .flex-center{
                    flex: 1;
                    background: blue;
                }
            </style>
            <div class="flex-left"></div>
            <div class="flex-center">
                <h1>我是flex方案</h1>
            </div>
            <div class="flex-right"></div>
        </section>

第四种 网格布局

<!-- 网格布局 -->
        <section class="layout grid">
            <style media="screen">
                .grid{
                    display: grid;
                    width: 100%;
                    grid-template-rows: 200px;
                    grid-template-columns: 300px auto 300px;
                }
                .grid-left{
                    width: 300px;
                    background: yellow
                }
                .grid-right{
                
                    width: 300px;
                    background: red
                }
                .grid-center{
                    flex: 1;
                    background: blue;
                }
            </style>
            <div class="grid-left"></div>
            <div class="grid-center">
                <h1>我是grid方案</h1>
            </div>
            <div class="grid-right"></div>
        </section>

最后我们一起来看看效果

layout

总结

纯float的三栏布局需要将中间的内容放在最后;

绝对定位的三栏布局:元素对其有点问题

flex布局最好,基本没有大的缺点。

grid布局兼容性不够好。

前端跨域的那些事

在我们日常开发中,经常碰到一些跨域的问题。

例如www.a.com想要获取到www.b.com的接口或者数据。就会因为同源策略的原因而无法获取到。

什么是同源策略

同源策略 same-orgin policy
不同域的客户端脚本在没有明确授权的情况下,不能读写对方的资源。

举例

http://a.taobao.com

地址 是否可以请求
https://a.taobao.com 不可以-协议不同
http://www.taobao.com 不可以-子域不同
http://taobao.com 不可以-子域不同
http://a.taobao.com:8080 不可以-端口不同
http://a,taobao.com/music/ 可以-同域

CROS

CROS是一种跨域的解决方案,其原理就是前台发送一个请求,而服务器就返回一个请求头授权访问。

请求示例

  • 客户端请求一个跨域的接口(默认带有Origin请求头)
  • 服务端收到后设置一个响应头并返回(Access-Control-Allow-Origin)授权
// 后台koa脚本
const koa = require('koa');
const bodyParser = require('koa-bodyparser');
const app = new koa();

//使用bodyParser
app.use(bodyParser());

app.use(async ctx =>{
    const url = ctx.url;

    if(ctx.headers.origin && ctx.query.cors){
    //设置请求头
        ctx.set('Access-Control-Allow-origin',ctx.headers.origin)
    }
    let res = {
        code:0,
        data:'success'
    }
    ctx.body = JSON.stringify(res);
})

app.listen(3000,()=>{
    console.log('服务器冲起来了');
})

后台在node 3000的端口运行,前台在http-server 3001 端口运行

//前台请求
  var $ = (id) => document.getElementById(id);
    var btn = $('button1');
    var btn2 = $('button2');
    function getData(callback, cors) {
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = () => {
            if (xhr.readyState === 4 && xhr.responseText) {
                callback(JSON.parse(xhr.responseText), xhr);
            }
        }
        xhr.open('get', `http://127.0.0.1:3000/${cors}`);
        xhr.send(null);
    }
    btn.addEventListener('click', () => {
        getData((response) => {
            console.log(`${response.data}`)
        }, '');
    });
    btn2.addEventListener('click', () => {
        getData((response) => {
           console.log(`${response.data}`)
        }, '?cors=1');
    });

  • CORS 优点在于方便简洁,只需要服务端设置响应头就好了。
  • 缺点在与一些IE不兼容 具体可以看 👉 CORS兼容性

JSONP

原理

  • 通过 script进行请求通过src请求
  • 创建一个回调函数,然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递
  • 将JSON数据填充进回调函数
//koa
const Koa = require('koa')
const bodyParser = require('koa-bodyparser')
const app = new Koa()
// 使用bodyParser 
app.use(bodyParser())

app.use(async ctx => {
  const url = ctx.url
  if (url.indexOf('/getData') === 0) { // 接口名称
    ctx.set('Content-Type', 'application/x-javascript')
    let res = {
        code:0,
        data:"我是一个jsonP跨域的数据!"
    }
    ctx.body = `${ctx.query.callback || 'jsonp'}(${JSON.stringify(res)})`
  } else {
    ctx.status = 404
    ctx.body = '404'
  }
})
app.listen(3000, () => {
  console.log('服务启动,打开 http://127.0.0.1:3000/')
})

后台在node 3000的端口运行,前台在http-server 8081 端口运行

/**
 * 自动发送 jsonp
 * @param {String} url
 * @param {Obj} data
 * @param {Function} callback
 */
function jsonp (url, data, callback) {
    var funcName = getFunctionName()
    data = data || {}
    data.callback = funcName
    url = parseUrl(url, serialize(data))
  
    window[funcName] = function (response) {
      // 这里可以看情况处理,比如如果是 jsonp 我们可以 parse 一下
      // data = JSON.parse(response)
      callback(response)
    }
  
    createScript(url)
  }
  /**
   * 序列化参数
   * jsonp 中参数只能是 GET 方式传递
   * @param {Obj} data
   */
  function serialize (data) {
    var ret = []
  
    Object.keys(data).forEach(item => {
      ret.push(encodeURIComponent(item) + '=' + encodeURIComponent(data[item]))
    })
  
    return ret.join('&')
  }
  
  /**
   * 处理 URL ,把参数拼上来
   * @param {String} url
   * @param {String} param
   */
  function parseUrl (url, param) {
    return url + (url.indexOf('?') === -1 ? '?' : '&') + param
  }
  
  /**
   * 必须要有一个全局函数,而且不能重名
   */
  function getFunctionName () {
    return ('jsonp_' + Math.random()).replace('.', '')
  }
  
  /**
   * 创建 script 标签并插到 body 中
   * @param {String} url
   */
  function createScript (url) {
    var doc = document
    var script = doc.createElement('script')
    script.src = url
    doc.body.appendChild(script)
  }
//调用
jsonp('http://127.0.0.1:3000/getData', {id:1}, (data) => {
    console.log(data)
})

jsonP实现效果

这是一个简单版的jsonP的实现,面试中也会常常被问到,并且手撸一个jsonP

具体的一个方法实现推荐一个 github 上面的一个库 👉 实现jsonP

iframe

原理

  • 借助iframe标签进行跨域
  • 将获取到的数据挂载到window.name

我们以三个页面为例和一个json为例

  • a.html -> 在端口 3001 运行
  • b.html -> 在端口 3002 运行
  • c.html
  • data.json
  • c去去掉用父级的方法,并传递获取到的数据。

大概的交互图为这样 👇
交互图

a为请求数据

<!--a.html-->
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>我是A页面</title>
</head>

<body>
    <div></div>
    <script>
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = () => {
            if (xhr.readyState === 4) {
                console.log(xhr.responseText);
            } else {
                console.log(xhr.status, xhr.statusText);
            }
        }
        xhr.open('get', 'http://127.0.0.1:3002/data.json');
        xhr.send(null);
    </script>
</body>
</html>

b为处理数据

<!--b.html-->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>处理数据</title>
</head>
<body>
  <script>
    var xhr = new XMLHttpRequest();
    xhr.onreadystatechange = () => {
      if (xhr.readyState === 4) {
        window.name = xhr.responseText;
        location.href = 'http://127.0.0.1:3001/c.html';
      } else {
        console.log(xhr.status, xhr.statusText);
      }
    }
    xhr.open('get', 'data.json');
    xhr.send(null);
  </script>
</body>
</html>

c为更新数据

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>传递数据</title>
</head>
<body>
  <script>
    parent.update(window.name);
  </script>
</body>
</html>

data数据

[
    {
        "data": "我是一条跨域数据"
    }
]

当我们调用a.html第一个AJAX方法的时候,毫无疑问肯定是跨域的,因为端口不一样

Access to XMLHttpRequest at 'http://127.0.0.1:3002/data.json' from origin 'http://127.0.0.1:3001' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

ajax-error

接下来我们修改一下A 的代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>我是A页面</title>
</head>

<body>
    <div></div>
    <iframe src="http://127.0.0.1:3002/b.html" frameborder="0"></iframe>
    <script>
        function update(data) {
            data = JSON.parse(data);
            var html = ['<ul>'];
            html.push(`<li>${data[0].data}</li>`);
            html.push('</ul>');
            document.querySelector('div').innerHTML = html.join('');
        }
    </script>
</body>
</html>

在改变了逻辑时

  • a.html 嵌套了一个与接口一样端口的网页
  • b.html 通过同端口的方式请求到了想用端口的数据,并且挂载到了全局的window.name上,并且跳转到c.html
  • c.html 通过parent调用a.htmlupdate的方法并把window.name值一同传递

此时我们就大功告成啦,页面显示出data.json的数据


以上就是我分享的前端跨域请求方式!

写的不好,仅供参考!

前端必须知道的网络

从输入地址到返回请求

  • 浏览器输入www.baidu.com -> 通过DNS查找IP地址
  • IP地址打包成一个HTTP包
  • 进入前台逻辑网络(TCP/IP) -> 物理网络 ->后台的逻辑网络(TCP/IP)
  • 之后再通过HTTP进行拆包,到达Server,在同理返回回来

TCP的三次握手

  • Server端进入一个Listen状态,等待接收请求
  • Client端发起请求并进入SYN_SENT,并且带着SYN seq=x到Server (x)为唯一的数字
  • Server接收到后进入SYN_RCVD并返回SYN sep=y ACK=x+1
  • Client进入ESTABLISHED连接状态,并告诉Server可以链接返回ACK=y+1
  • Server进入ESTABLISHED状态

TCP四次挥手

  • Client进入FIN_WAIIT_1传递FIN seq=x+2 ACk=y+1,Server进入CLOSE_WAIT返回ACK x+3(server不知道自己还有没有包发送完毕,所以不能立马关闭)
  • Client进入FIN_WAIIT_2,Server端状态变成LAST_ACK关闭的时候返回FIN seq=y+1
  • Client进入TIME_WAIT,返回给ServerACk=y+2

HTTP 报文结构

HTTP状态码

  • 1xx 信息,服务器收到请求,需要请求者继续执行操作
  • 2xx 成功,操作被成功接收并处理
  • 3xx 重定向,需要进一步的操作以完成请求
  • 4xx 客户端错误,请求包含语法错误或无法完成请求
  • 5xx 服务器错误,服务器在处理请求的过程中发生了错误

  • 200 请求成功
  • 301 永久重定向
  • 302 临时重定向
  • 304 缓存
  • 401 要求身份确认
  • 404 未找到
  • 500 服务器内部错误

手写一个jsonp

/**
 * 自动发送 jsonp
 * @param {String} url
 * @param {Obj} data
 * @param {Function} callback
 */
function jsonp(url, data, callback) {
  var funcName = getFunctionName()
  data = data || {}
  data.callback = funcName
  url = parseUrl(url, serialize(data))

  window[funcName] = function (response) {
    // 这里可以看情况处理,比如如果是 jsonp 我们可以 parse 一下
    // data = JSON.parse(response)
    callback(response)
  }

  createScript(url)
}

/**
 * 序列化参数
 * jsonp 中参数只能是 GET 方式传递
 * @param {Obj} data
 */
function serialize(data) {
  var ret = []

  Object.keys(data).forEach(item => {
    ret.push(encodeURIComponent(item) + '=' + encodeURIComponent(data[item]))
  })

  return ret.join('&')
}

/**
 * 处理 URL ,把参数拼上来
 * @param {String} url
 * @param {String} param
 */
function parseUrl(url, param) {
  return url + (url.indexOf('?') === -1 ? '?' : '&') + param
}

/**
 * 这里就是对 jsonp 的理解了,必须要有一个全局函数,而且不能重名
 */
function getFunctionName() {
  return ('jsonp_' + Math.random()).replace('.', '')
}

/**
 * 创建 script 标签并插到 body 中
 * @param {String} url
 */
function createScript(url) {
  var doc = document
  var script = doc.createElement('script')
  script.src = url

  doc.body.appendChild(script)
}

Javascript 变量、作用域

引用类型和基本类型

  1. ES5中目前有UndefinedNullBooleanNumberString
  2. 引用类型的值是保存在内存中的对象。
  3. 基本类型值指的是简单的数据段,而引用类型值指那些可能由多个值构成的对象

复制变量值

  1. 基本类型的值是独立空间存储的并且存储在栈中
//基本类型
var a = 1;
var b = a;
b = 2;
console.log(a,b)// 1 2

基本类型

//引用类型
var obj = {a:1};
var copyObj = obj;
obj.a = 2;
console.log(obj.a,copyObj.a)
  1. 引用类型的值是也是独立空间存储并且存储在堆中,如果两个变量引用同个对象,指针会指向同一个对象。(所以引发出深浅拷贝的考点)

引用类型

参数传递

  1. 把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样(是引用类型那就是引用类型,是基本类型就是基本类型)
//基本类型
var a = 1;
function fn(a) {
  a = 2;
  console.log(a)//2
}
fn(a)
console.log(a)//1

//引用类型
var obj = {
	a:1,
}
function fn1(o) {
  o.a = 2;
  console.log(o.a);
}
fn1(obj)
console.log(obj.a)

执行环境及作用域

作用域分为全局作用域局部作用域

  1. 全局下的作用域在程序关闭时才会注销
  2. 局部作用域在执行完毕后会被注销

每个函数都有自己的执行环境

作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问

  1. 内部环境可以通过作用域链访问所有的外部环境
  2. 外部环境不能访问内部环境中的任何变量和函数
  3. 局部作用域可以足级向上搜索如果没有找到就是未定义,全局作用域不可以向下搜索
//局部访问全局
var a = 1;
function fn() {
  console.log(a) //1 局部作用域没有1 所以向上找外一层作用域的a
}
fn()

// 局部作用域向上搜索
var a = 1;
function test() {
	var b = 2;
  function test2() {
    console.log(a,b)//1,2
  }
  test2()
}
test()

//全局作用域不可以向下搜索
function fn1() {
  var b = 1;
  console.log(b);
}
fn1();
console.log(b)// b is not defined

块级作用域

es5javascript不像c++语言相似有块级作用域这个说法

  1. JavaScript 中,if语句中的变量声明会将变量添加到当前的执行环境;
  2. 初始化变量时没有使用var声明,该变量会自动被添加到全局环境;
// a相当于在全局作用域下
if(true){
	var a = 1;
}
console.log(a)

function fn() {
  if(true){
  	var b = 1;
  }
  if(true){
  	 c = 2;
  }
  if(false){
  	var d = 3;
  }
  console.log(b)//1
  console.log(d)//undefined 变量提升
}
fn()
console.log(c)//2 c没有var 声明 自动添加到全局环境

总结

  • 基本类型值在内存中占据固定大小的空间,因此被保存在栈内存中;
  • 引用类型的值是对象,保存在堆内存中(引用类型值的变量实际上包含的并不是对象本身,而是一个指向该对象的指针);
  • 执行环境有全局执行环境和局部执行环境之分;
  • 函数的局部环境不仅有权访问函数作用域中的变量,而且有权访问其包含(父)环境,乃至全局环境;
  • 初始化变量时没有使用var声明,该变量会自动被添加到全局环境

js中new都发什么什么

/**
 * 1.创建一个新的对象
 * 2.将函授的作用域赋值给了新对象(改变this)
 * 3.为这个对象添加属性
 * 4.返回一个新的对象
 * @returns {*}
 */
function myObj(){
    let obj = {};
    let result;
    //arguments 是一个伪数组 所以不能用shift 所以创建一个空数组
    let Con = [].shift.call(arguments);
    //指向原型
    obj.__proto__ = Con.prototype;
    //绑定this。 apply方式
    result = Con.apply(obj,arguments);
    // 类型判断
    return result instanceof Object ? result : obj;
}

继承的几种方式以及特点

/**
 * 继承 call apply
 * 缺点 只继承了父类构造函数的东西 原型连上的东西继承不到
 */

 function Parent(){
     this.name = 'parent';
 }
 Parent.prototype.run = function(){}
 function Child(){
     Parent.call(this)
     this.type = 'child'
 }
 var child = new Child();
 console.log(child.name)

 /**
  * 利用原型链继承
  * Child1.prototype 是一个对象可以任意赋值 
  * 在父级改变值时 实例公用对象 值会污染
  */

  function Parent1(){
      this.name = 'parent'
      this.play = [1,2,3,4]
  }
  function Child1(){
      this.type = 'child1'
  }

  Child1.prototype = new Parent1();
  var s1 = new Child1();
  var s2 = new Child1();
  s1.play.push(5);
  console.log(s1.play === s2.play)
  console.log(new Child1().__proto__)

  /**
   * 组合方式优化
   * 无法区分s3的 instanceof 到底是谁的
   */

   function Parent2(){
       this.name = "parent"
   }
   function Child2(){
       Parent2.call(this)
       this.type = "child"
   }
   Child2.prototype =Parent2.prototype;

    var s3 = new Child2();
    var s4 = new Child2();
    console.log(s3  instanceof Child2)
    console.log(s3  instanceof Parent2)



    /**
     * 最优写法
     * 
     */
    function Person(name) {
        this.name = name;
    }
    Person.prototype.sayHello = function() {
        console.log('Hi! My name is ' + this.name + '.');
    }
    
    function Student(name, grade) {
        Person.call(this, name)
        this.grade = grade;
    }
    // 继承原型
    inheritPrototype(Student, Person);
    Student.prototype.sayGrade = function() {
        console.log('I am Grade ' + this.grade + '.');
    }
    
    function inheritPrototype(subType, superType){
        //复制父类原型到新的对象
        var protoType = Object.create(superType.prototype);
        //新的对象重置constructor
        protoType.constructor = subType;
        //修改子类原型
        subType.prototype = protoType;
    }

记一次Nginx体验

小白玩Nginx——入门

server

  • listen 监听的端口号
  • server_name 监听的地址
  • location 指向地址
  • proxy_pass 代理地址
  • root 路径
  • index 显示页面的名称

具体配置

前端使用 Vue
后端使用 Node

server {
         listen       80;                             //监听80端口
         server_name freddyhx.xyz;                    //监听访问地址
         location / {                                 //默认路径
             root   /home/blog-node/server/dist/;     //Vue打包后的路径
             index  index.html index.htm;             //显示主页名字
        }
        location /api/ {                              //Vue访问api文件时做一个Node代理
             proxy_pass http://127.0.0.1:8080;        //node运行的地址和端口
        }
}

当有多个项目可以参考下面的配置

//项目1
server {
         listen       80;                             //监听80端口
         server_name freddyhx.xyz;                    //监听访问地址
         location / {                                 //默认路径
             root   /home/blog-node/server/dist/;     //Vue打包后的路径
             index  index.html index.htm;             //显示主页名字
        }
        location /api/ {                              //Vue访问api文件时做一个Node代理
             proxy_pass http://127.0.0.1:8080;        //node运行的地址和端口
        }
}

//项目2

 server {
         listen       80;                             //监听80端口
         server_name test.freddyhx.xyz;               //监听访问地址
         location / {                                 //默认路径
             root /home/test/;                        //路径
             index index.html;                        //显示页面
         }
    }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.