主頁 > 企業開發 > [筆記]你不知道的JavaScript(上)

[筆記]你不知道的JavaScript(上)

2020-09-19 20:58:36 企業開發

前言

文章只記錄理解以及容易遺忘的知識點,

詞法作用域、塊作用域

詞法作用域

詞法作用域:簡單的說,詞法作用域就是定義在詞法階段的作用域,換句話說,詞法作用域就是在你寫代碼時將變數和塊作用域寫在哪里來決定的,因此在詞法分析器處理代碼時會保持作用域不變(大部分情況是這樣的),

當然有一些欺騙詞法作用域的方法,這些方法在詞法分析器處理后依然可以改變作用域,

欺騙詞法作用域的方法有:

  • eval():可以接受一個字串作為引數,
  • with:通常被當作重復參考同一個物件中的多個屬性的快捷方式,可以不需要重復參考物件本身,
var obj = {    a:1,    b:2,    c:3};//單調乏味的重復"obj"obj.a=2;obj.b=3;obj.c=4;//簡單的快捷方式with(obj){    a=2;    b=3;    c=4;}

塊作用域

  • with
  • try/catch
  • let
  • const

簡單解釋下箭頭函式:簡單來說,箭頭函式在涉及this系結時的行為和普通函式的行為完全不一致,它放棄了所有普通this系結規則,取而代之的是用當前的詞法作用域覆寫了this本來的值,

作用域閉包

現代的模塊機制

大多數模塊依賴加載器/管理器本質上都是將這種模塊定義封裝進一個友好的API,這里并不會研究某個具體的庫,為了宏觀了解簡單介紹一些核心概念:

var MyModules = (function Manager(){    var modules = {};    function define(name,deps,impl){        for(var i = 0; i < deps.length; i++){            deps[i] = modules[deps[i]];        }        modules[name] = impl.apply(impl,deps);    }        function get(name){        return modules[name];    }    return {        define:define,        get:get    }})();

這段代碼的核心是modules[name] = impl.apply(impl,deps),為了模塊的定義引入了包裝函式(可以傳入任何依賴),并且將回傳值,也就是模塊的API,存盤在一個根據名字來管理的模塊串列中,

下面用它來如何定義模塊:

MyModules.define("bar",[],function(){    function hello(who){        return "Let me introduce:" + who;    }    return {        hello:hello    }});MyModules.define("foo",['bar'],function(bar){    var hungry = "hippo";    function awesome(){        console.log(bar.hello(hungry).toUpperCase());    }    return {        awesome:awesome    }});var bar = MyModules.get("bar");var foo = MyModules.get("foo");console.log(bar.hello("hippo")); //Let me introduce:hippofoo.awesome();  //LET ME INTRODUCE:HIPPO

 “foo”和“bar”模塊都是通過一個回傳公共API的函式來定義的,“foo”甚至接受“bar”的示例作為依賴引數,并能相應地使用它,

未來的模塊機制

bar.jsfunction hello(who){    return "Let me introduce:" + who;}export hello;foo.js//僅從"bar"模塊匯入hello()import hello from "bar";var hungry = "hippo";function awesome(){    console.log(hello(hungry).toUpperCase());}export awesome;baz.js//匯入完整的"foo"和"bar"模塊module foo from "foo";module bar from "bar";console.log(bar.hello("hippo")); //Let me introduce:hippofoo.awesome();  //LET ME INTRODUCE:HIPPO

 import可以將一個模塊中的一個或多個API匯入到當前作用域中,并分別系結在一個變數上(在我們的例子里是hello),module會將整個模塊的API匯入并系結到一個變數上(在我們的例子里是foo和bar).export會將當前模塊的一個識別符號(變數、函式)匯出為公共API,這些操作可以在模塊定義中根據需要使用任意多次,

動態作用域

function foo(){    console.log(a); //2}function bar(){    var a = 3;    foo();}var a = 2;bar(); 

如果JS具有動態作用域,那么列印的值就是3,而不是2了,需要明確的是,事實上JS并不具有動態作用域,它只有詞法作用域,簡單明了,但是this機制某種程度上很像動態作用域,

主要區別:詞法作用域是在寫代碼或者說定義時確定的,而動態作用域是在運行時確定的,(this也是!)詞法作用域關注函式在何處宣告,而動態作用域關注函式從何處呼叫,最后,this關注函式如何呼叫,這就表明了this機制和動態作用域之間的關系那么緊密,

this決議

JS有許多的內置函式,都提供了一個可選的引數,通常被成為“背景關系”(context),其作用和bind(...)一樣,確保你的回呼函式使用指定的this,如下例子:

function foo(el){    console.log(el,this.id);}var obj = {    id:"awesome"};//呼叫foo(...)時把this系結到obj[1,2,3].forEach(foo,obj); //結果:1 "awesome" 2 "awesome"  3 "awesome"

 bind()

bind()方法創建一個新的函式,在呼叫時設定this關鍵字為提供的值,并在呼叫新函式時,將給定引數串列作為原函式的引數序列的前若干項,

語法:function.bind(thisArg[, arg1[, arg2[, ...]]])

簡單例子:

var module = {  x: 42,  getX: function() {    return this.x;  }}var unboundGetX = module.getX;console.log(unboundGetX()); // The function gets invoked at the global scope// expected output: undefinedvar boundGetX = unboundGetX.bind(module);console.log(boundGetX());// expected output: 42

你可以將下面這段代碼插入到你的腳本開頭,從而使你的 bind() 在沒有內置實作支持的環境中也可以部分地使用bind,

if (!Function.prototype.bind) {  Function.prototype.bind = function(oThis) {    if (typeof this !== 'function') {      // closest thing possible to the ECMAScript 5      // internal IsCallable function      throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');    }    var aArgs   = Array.prototype.slice.call(arguments, 1),        fToBind = this,        fNOP    = function() {},        fBound  = function() {          // this instanceof fBound === true時,說明回傳的fBound被當做new的建構式呼叫          return fToBind.apply(this instanceof fBound                 ? this                 : oThis,                 // 獲取呼叫時(fBound)的傳參.bind 回傳的函式入參往往是這么傳遞的                 aArgs.concat(Array.prototype.slice.call(arguments)));        };    // 維護原型關系    if (this.prototype) {      // Function.prototype doesn't have a prototype property      fNOP.prototype = this.prototype;     }    // 下行的代碼使fBound.prototype是fNOP的實體,因此    // 回傳的fBound若作為new的建構式,new生成的新物件作為this傳入fBound,新物件的__proto__就是fNOP的實體    fBound.prototype = new fNOP();    return fBound;  };}

 詳細參考地址:《MDN:Function.prototype.bind()》

物件

物件鍵只能是字串

symbol 出現之前,物件鍵只能是字串,如果試圖使用非字串值作為物件的鍵,那么該值將被強制轉換為字串,如下:

const obj = {};obj.foo = 'foo';obj['bar'] = 'bar';obj[2] = 2;obj[{}] = 'someobj';console.log(obj);

結果:

2:2[object Object]:"someobj"bar:"bar"foo:"foo"

屬性描述符

從ES5開始,所有的屬性都具備了屬性描述符,

思考如下代碼,使用Object.getOwnPropertyDescriptor()

var myObject = {    a:2};var result = Object.getOwnPropertyDescriptor(myObject,"a");console.log(result);

得到的結果如下:

{    configurable:true,    enumerable:true,    value:2,    writable:true}

這個普通的物件屬性對應的屬性描述符除了有value值為2,還有另外三個特性:writable(可寫)enumerable(可列舉)configurable(可配置)

使用Object.defineProperty()來添加一個新屬性或者修改一個已有屬性(如果它是configurable)并對特性進行設定,

writable

如下代碼:

var myObject = {}Object.defineProperty(myObject,"a",{    value:2,    writable:false, //不可寫    configurable:true,    enumerable:true});myObject.a = 3;console.log(myObject.a); //2

如果在嚴格模式下,上面這寫法報錯:

"use strict";var myObject = {}Object.defineProperty(myObject,"a",{    value:2,    writable:false, //不可寫    configurable:true,    enumerable:true});myObject.a = 3; //Uncaught TypeError: Cannot assign to read only property 'a' of object '#<Object>'

configurable

var myObject = {}Object.defineProperty(myObject,"a",{    value:2,    writable:true,     configurable:false, //不可配置    enumerable:true});myObject.a = 5;console.log(myObject.a); //5delete myObject.a;console.log(myObject.a); //configurable:false,禁止洗掉這個屬性Object.defineProperty(myObject,"a",{    value:6,    writable:true,     configurable:true,     enumerable:true}); //TypeError: Cannot redefine property: a

上面代碼可以看出,設定configurable為false是單向操作,無法撤銷,同時還會禁止洗掉這個屬性,

注意:要注意一個小小的例外,即使屬性configurable:false,我們還是可以把writable的狀態有true改為false,但是無法由false改為true,

enumerable

從名字可以看出來,這個描述符控制的是屬性是否出現在物件的屬性列舉中,比如for...in回圈,

不變性

有時候我們希望屬性或者物件是不可改變的,ES5中有很多方法可以實作,

物件常量

結合writable:false和configurable:false就可以真正的創建一個常量屬性(不可修改、重定義或者洗掉),

var myObject = {}Object.defineProperty(myObject,"a",{    value:2,    writable:false,     configurable:false});

禁止擴展Object.preventExtensions()

如果你想禁止一個物件添加新的屬性并且保留已有屬性,可以使用Object.preventExtensions()

var myObject = {    a:2};Object.preventExtensions(myObject);myObject.b = 3;console.log(myObject.b); //undefined

在嚴格模式下,將會拋出TypeError錯誤,

密封Object.seal()

Object.seal()會創建一個“密封”的物件,這個方法實際上會在現有物件上呼叫Object.preventExtensions()并把所有現有屬性標記為configurable:false,

所以,密封之后不僅不能添加新的屬性,也不能重新配置或者洗掉任何屬性(雖然可以修改屬性的值),

凍結Object.freeze()

Object.freeze()會創建一個凍結物件,這個方法實際上會在一個現有物件上呼叫Object.seal()并把所有“資料訪問”屬性標記為writable:false,這樣就無法修改它們的值,

這個方法是你可以應用在物件上的級別最高的不可變性,它會禁止對于物件本身及其任意直接屬性的修改(這個物件參考的其它物件是不受影響的),

你可以“深度凍結”一個物件,具體方法為,首先在這個物件上呼叫Object.freeze(),然后遍歷它所有參考的所有物件并在這些物件上呼叫Object.freeze(),但你一定要小心,因為這樣做,你可能會在無意中凍結其它(共享)物件,

Getter和Setter

物件默認的[[Put]]和[[Get]]操作分別可以控制屬性值的設定和獲取,

當你給一個屬性定義getter、setter或者兩者都有時,這個屬性會被定義為“訪問描述符”(和“資料描述符”相對的),對于訪問描述符來說,JS會忽略它們的value和writable特性,取而代之的是關心set和get(還有configurable和enumerable)特性,

思考如下代碼:

var myObject = {    get a(){        return 2;    }};Object.defineProperty(myObject,"b",{    get:function(){        return this.a * 2;    },    enmuerable:true})console.log(myObject.a); //2console.log(myObject.b); //4

為了讓屬性更合理,還應該定義setter,setter會覆寫單個屬性默認的[[Put]](也被稱為賦值)操作,通常來說getter和setter是成對出現的,

var myObject = {    get a(){        return this._a_;    },    set a(val){        this._a_ = val * 2;    }};myObject.a = 2;console.log(myObject.a); //4

遍歷

for...in回圈可以用來遍歷物件的可列舉屬性串列(包括[[Prototype]]鏈),

ES5增加了一些陣列的輔助迭代器,包括forEach()、every()和some(),每種迭代器都可以接受一個回呼函式并把它應用到陣列的每個元素上,唯一的區別就是它們對于回呼函式回傳值的處理方式不同,

  • forEach():會遍歷陣列中的所有值并忽略回呼函式的回傳值,
  • every():會一直運行直到回呼函式回傳false(或者“假”值),
  • some():會一直運行直到回呼函式回傳true(或者“真”值),

注:every()和some()中特殊的回傳值和普通for回圈中的break陳述句相似,他們會提前終止遍歷,

使用for...in遍歷物件是無法直接獲得屬性值的 ,它只是遍歷了物件中所有可以列舉的屬性,你需要手動獲取屬性值,

ES6增加了一種用來遍歷陣列的for...of回圈語法(如果物件本身定義了迭代器的話也可以遍歷物件):

var myArray = [1,2,3];for(var v of myArray){    console.log(v); //1 2 3};

for...of回圈首先會向被訪問物件請求一個迭代器物件,然后通過呼叫迭代器物件的next()方法來遍歷所有回傳值,

陣列有內置的@@iterator,因此for...of可以直接應用在陣列上,我們使用內置的@@iterator來手動遍歷陣列,看看它是怎么作業的:

var myArray = [1,2,3];var it = myArray[Symbol.iterator]();var next1 = it.next();var next2 = it.next();var next3 = it.next();var next4 = it.next();console.log(next1); //{value: 1, done: false}console.log(next2); //{value: 2, done: false}console.log(next3); //{value: 3, done: false}console.log(next4); //{value: undefined, done: true}

注:我們使用ES6中的符號Symbol.iterator來獲取物件的@@iterator內部屬性,@@iterator本身并不是一個迭代器物件,而是一個回傳迭代器物件的函式--這一點非常精妙并且非常重要,

普通的物件并沒有內置的@@iterator,所以無法自動完成for...of遍歷,當然,你也可以給任何想遍歷的物件定義@@iterator,如下代碼:

var myObject = {    a:2,    b:3};Object.defineProperty(myObject,Symbol.iterator,{    enumerable:false,    writable:false,    configurable:true,    value:function(){        var o = this,            idx = 0,            ks = Object.keys(o);        return {            next:function(){                return {                    value:o[ks[idx++]],                    done:(idx > ks.length)                }            }        }    }});//手動遍歷myObjectvar it = myObject[Symbol.iterator]();var next1 = it.next();var next2 = it.next();var next3 = it.next();console.log(next1); //{value: 2, done: false}console.log(next2); //{value: 3, done: false}console.log(next3); //{value: undefined, done: true}//用for...of遍歷myObjectfor(var v of myObject){    console.log(v);}//2//3

注:我們使用Object.defineProperty()定義了我們自己的@@iterator(主要是為了讓它不可列舉),不過注意,我們把符號當做可計算屬性名,此外,也可以直接在定義物件時進行宣告,比如:

var myObject = {    a:2,    b:3,    [Symbol.iterator]:function(){        /*..*/    }};

對于用戶定義的物件來說,結合for...of和用戶自定義的迭代器可以組成非常強大的物件操作工具,

再看一個例子,寫一個迭代器生成“無限個”亂數,我們添加一條break陳述句,防止程式被掛起,代碼如下:

var randoms = {    [Symbol.iterator]:function(){        return {            next:function(){                return {                    value:Math.random()                }            }        }    }};var random_pool = [];for(var n of randoms){    random_pool.push(n);    console.log(n);    //防止無限運行    if(random_pool.length === 10) break;}

 constructor 屬性

語法:object.constructor

回傳值:物件的constructor屬性回傳創建該物件的函式的參考,

// 字串:String()var str = "張三";alert(str.constructor); // function String() { [native code] }alert(str.constructor === String); // true // 陣列:Array()var arr = [1, 2, 3];alert(arr.constructor); // function Array() { [native code] }alert(arr.constructor === Array); // true // 數字:Number()var num = 5;alert(num.constructor); // function Number() { [native code] }alert(num.constructor === Number); // true // 自定義物件:Person()function Person(){    this.name = "CodePlayer";}var p = new Person();alert(p.constructor); // function Person(){ this.name = "CodePlayer"; }alert(p.constructor === Person); // true // JSON物件:Object()var o = { "name" : "張三"};alert(o.constructor); // function Object() { [native code] }alert(o.constructor === Object); // true // 自定義函式:Function()function foo(){    alert("CodePlayer");}alert(foo.constructor); // function Function() { [native code] }alert(foo.constructor === Function); // true // 函式的原型:bar()function bar(){    alert("CodePlayer");}alert(bar.prototype.constructor); // function bar(){ alert("CodePlayer"); }alert(bar.prototype.constructor === bar); // true

原型

物件關聯

使用Object.create()可以完美的創建我們想要的關聯關系,

var foo = {    something:function(){        console.log("tell me something");    }};var bar = Object.create(foo);bar.something(); //tell me something

Object.create()的polyfill代碼,由于Object.create()是在ES5中新增的函式,所以在舊版瀏覽器中不支持,使用下面這段代碼兼容:

if(!Object.create){    Object.create = function(o){        function F(){};        F.prototype = o;        return new F();    }}

標準ES5中內置的Object.create()函式還提供了一系列的附加功能,如下代碼:

var anotherObject= {    a:2};var myObject = Object.create(anotherObject,{    b:{        enumerable:false,        writable:true,        configurable:false,        value:3    },    c:{        enumerable:true,        writable:false,        configurable:false,        value:4    }});console.log(myObject.hasOwnProperty('a')); //falseconsole.log(myObject.hasOwnProperty('b')); //trueconsole.log(myObject.hasOwnProperty('c')); //trueconsole.log(myObject.a); //2console.log(myObject.b); //3console.log(myObject.c); //4

Object.create(..)第二個引數指定了需要添加到新物件中的屬性名以及這些屬性的屬性描述符,

關聯關系是備用

下面代碼可以讓你的API設計不那么“神奇”,同時仍然能發揮[[Prototype]]關聯的威力:

var anotherObject= {    cool:function(){        console.log('cool!');    }};var myObject = Object.create(anotherObject);myObject.deCool = function(){    this.cool();}myObject.deCool();

 行為委托

面向委托的設計:比較思維模型

下面比較下這兩種設計模式(面向物件和物件關聯)具體的實作方法,下面典型的(“原型”)面向物件風格:

function Foo(who){    this.me = who;}Foo.prototype.identify = function(){    return "I am " + this.me;}function Bar(who){    Foo.call(this,who);}Bar.prototype = Object.create(Foo.prototype);Bar.prototype.speak = function(){    console.log("hello, " + this.identify() + ".");}var b1 = new Bar("b1");var b2 = new Bar("b2");b1.speak(); //hello, I am b1.b2.speak(); //hello, I am b2.

子類Bar繼承了父類Foo,然后生成了b1和b2兩個實體,b1委托了Bar.prototype,后者委托了Foo.prototype,這種風格很常見,

物件關聯風格實作相同的功能:

var Foo = {    init:function(who){        this.me = who;    },    identify:function(){        return "I am " + this.me;    }};var Bar = Object.create(Foo);Bar.speak = function(){    console.log("hello, " + this.identify() + ".");}var b1 = Object.create(Bar);b1.init("b1");var b2 = Object.create(Bar);b2.init("b2");b1.speak(); //hello, I am b1.b2.speak(); //hello, I am b2.

這段代碼同樣利用[[Prototype]]把b1委托給Bar并把Bar委托給Foo,和上一段代碼一模一樣,我們仍然實作了三個物件直接的關聯,

類與物件

web開發一種典型的前端場景:創建UI控制元件(按鈕,下拉串列等等),

控制元件“類”

下面代碼是在不使用任何“類”輔助庫或者語法的情況下,使用純JavaScript實作類風格的代碼:

//父類function Widget(width,height){    this.width = width || 50;    this.height = height || 50;    this.$elem = null;};Widget.prototype.render = function($where){    if(this.$elem){        this.$elem.css({            width:this.width + "px",            height:this.height + "px"        }).appendTo($where);    }};//子類function Button(width,height,label){    //呼叫"super"建構式    Widget.call(this,width,height);    this.label = label || "Default";    this.$elem = $("<button>").text(this.label);}//讓子類“繼承”WidgetButton.prototype = Object.create(Widget.prototype);//重寫render()Button.prototype.render = function($where){    Widget.prototype.render.call(this,$where);    this.$elem.click(this.onClick.bind(this));}Button.prototype.onClick = function(evt){    console.log("Button '"+this.label+"'clicked! ");};$(document).ready(function(){    var $body = $(document.body);    var btn1 = new Button(125,30,"Hello");    var btn2 = new Button(150,40,"World");    btn1.render($body);    btn2.render($body);});

ES6的class語法糖

class Widget {    constructor(width,height) {        this.width = width || 50;        this.height = height || 50;        this.$elem = null;    }    render($where){        if(this.$elem){            this.$elem.css({                width:this.width + "px",                height:this.height + "px"            }).appendTo($where);        }    }}class Button extends Widget {    constructor(width,height,label){        super(width,height);        this.label = label || "Default";        this.$elem = $("<button>").text(this.label);    }    render($where){        super($where);        this.$elem.click(this.onClick.bind(this));    }    onClick(evt){        console.log("Button '"+this.label+"'clicked! ");    }}$(document).ready(function(){    var $body = $(document.body);    var btn1 = new Button(125,30,"Hello");    var btn2 = new Button(150,40,"World");    btn1.render($body);    btn2.render($body);});

委托控制元件物件

下面例子使用物件關聯風格委托來更簡單地實作Wiget/Button:

var Widget = {    init:function(width,height){        this.width = width || 50;        this.height = height || 50;        this.$elem = null;    },    insert:function($where){        if(this.$elem){            this.$elems.css({                width:this.width + "px",                height:this.height + "px"            }).appendTo($where);        }    }}var Button = Object.create(Widget);Button.setup = function(width,height,label){    //委托呼叫    this.init(width,height);    this.label = label || "Default";    this.$elem = $("<button>").text(this.label);}Button.build = function($where){    //委托呼叫    this.insert($where);    this.$elem.click(this.onClick.bind(this));}Button.onClick = function(evt){    console.log("Button '"+this.label+"'clicked! ");}$(document).ready(function(){    var $body = $(document.body);        var btn1 = Object.create(Button);    btn1.setup(125,30,"Hello");        var btn2 = Object.create(Button);    btn2.setup(150,40,"World");        btn1.build($body);    btn2.build($body);})

物件關聯可以更好的支持關注分離(separation of concerns)原則,創建和初始化并不需要合并成一個步驟,

 

<style></style><style></style><style></style>

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/83658.html

標籤:JavaScript

上一篇:js通過閉包實作多個相同事件只需系結一次

下一篇:JavaScript箭頭函式

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 使用Django Rest framework搭建Blog

    在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處于上升趨勢,但是Rest API還是使用的更廣泛一些. 所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Qu ......

    uj5u.com 2023-04-20 08:17:54 more
  • 記錄-new Date() 我忍你很久了!

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 大家平時在開發的時候有沒被new Date()折磨過?就是它的諸多怪異的設定讓你每每用的時候,都可能不小心踩坑。造成程式意外出錯,卻一下子找不到問題出處,那叫一個煩透了…… 下面,我就列舉它的“四宗罪”及應用思考 可惡的四宗罪 1. Sa ......

    uj5u.com 2023-04-20 08:17:47 more
  • 使用Vue.js實作文字跑馬燈效果

    實作文字跑馬燈效果,首先用到 substring()截取 和 setInterval計時器 clearInterval()清除計時器 效果如下: 實作代碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ......

    uj5u.com 2023-04-20 08:12:31 more
  • JavaScript 運算子

    JavaScript 運算子/運算子 在 JavaScript 中,有一些運算子可以使代碼更簡潔、易讀和高效。以下是一些常見的運算子: 1、可選鏈運算子(optional chaining operator) ?.是可選鏈運算子(optional chaining operator)。?. 可選鏈操 ......

    uj5u.com 2023-04-20 08:02:25 more
  • CSS—相對單位rem

    一、概述 rem是一個相對長度單位,它的單位長度取決于根標簽html的字體尺寸。rem即root em的意思,中文翻譯為根em。瀏覽器的文本尺寸一般默認為16px,即默認情況下: 1rem = 16px rem布局原理:根據CSS媒體查詢功能,更改根標簽的字體尺寸,實作rem單位隨螢屏尺寸的變化,如 ......

    uj5u.com 2023-04-20 08:02:21 more
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 08:01:50 more
  • 如何在 vue3 中使用 jsx/tsx?

    我們都知道,通常情況下我們使用 vue 大多都是用的 SFC(Signle File Component)單檔案組件模式,即一個組件就是一個檔案,但其實 Vue 也是支持使用 JSX 來撰寫組件的。這里不討論 SFC 和 JSX 的好壞,這個仁者見仁智者見智。本篇文章旨在帶領大家快速了解和使用 Vu ......

    uj5u.com 2023-04-20 08:01:37 more
  • 【Vue2.x原始碼系列06】計算屬性computed原理

    本章目標:計算屬性是如何實作的?計算屬性快取原理以及洋蔥模型的應用?在初始化Vue實體時,我們會給每個計算屬性都創建一個對應watcher,我們稱之為計算屬性watcher ......

    uj5u.com 2023-04-20 08:01:31 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:01:10 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:00:32 more