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

来源:https://www.cnblogs.com/moqiutao/archive/2020/05/23/10550507.html
-Advertisement-
Play Games

前言 文章只記錄理解以及容易遺忘的知識點。 詞法作用域、塊作用域 詞法作用域 詞法作用域:簡單的說,詞法作用域就是定義在詞法階段的作用域。換句話說,詞法作用域就是在你寫代碼時將變數和塊作用域寫在哪裡來決定的,因此在詞法分析器處理代碼時會保持作用域不變(大部分情況是這樣的)。 當然有一些欺騙詞法作用域 ...


前言

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

詞法作用域、塊作用域

詞法作用域

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

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

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

  • 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:hippo
foo.awesome();  //LET ME INTRODUCE:HIPPO

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

未來的模塊機制

bar.js
function 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:hippo
foo.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: undefined

var 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); //5
delete 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); //2
console.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)
                }
            }
        }
    }
});

//手動遍歷myObject
var 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遍歷myObject
for(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')); //false
console.log(myObject.hasOwnProperty('b')); //true
console.log(myObject.hasOwnProperty('c')); //true

console.log(myObject.a); //2
console.log(myObject.b); //3
console.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);
}

//讓子類“繼承”Widget
Button.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)原則,創建和初始化並不需要合併成一個步驟。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在前後端數據交互的過程中,為了能夠減少ajax請求次數,減輕帶寬壓力,後端往往會將當前介面所需的參數以對象的形式集體返回。這樣就導致一個問題:對象內欄位屬性過多,而有些小組件功能又壓根不需要這麼一個大對象參數(主要是對象屬性過多,難得理,也懶得找),這時就需要對這個大對象做再加工處理。 比如:將小組 ...
  • h5+ 開發微信、QQ分享功能 此處只做微信網頁分享示例代碼 方式一、JS+HTML+h5Plus 1.html代碼 <div class="button" onclick="shareWeb()">分享網頁</div> 2.JS代碼 // H5 plus事件處理function plusReady ...
  • 今天終於把樸靈老師寫的《深入淺出Node.js》給學習完了, 這本書不是一本簡單的Node入門書籍,它沒有停留在Node介紹或者框架、庫的使用層面上,而是從不同的視角來揭示Node自己內在的特點和結構。建議有一定Node基礎或者做過Node方面的小項目的同學閱讀,看完以後你的思維會有很奇特的碰撞,我 ...
  • 現在這個社會是信息爆炸的社會,各個網站、app上鋪天蓋地的都是各種新聞和信息。 為了獲取信息,我們每天都要進行各種麻煩的操作,打開各種網站或者手機app,操作顯得低效,後來發現了一個神器,那就是RSS。 什麼是RSS RSS中文名是簡易信息聚合,就是讓網站一個按照一定周期更新網站的文章概要內容(有些 ...
  • 今天小編要跟大家分享的文章是關於想要學習web前端需要掌握哪些技能和工具?互聯網的快速發展和激烈競爭,使得用戶體驗成為一個重要的關註點,導致專業前端工程師成為熱門職業,各大公司對前端工程師的需求量都很大,要求也越來越高,優秀的前端工程師更是稀缺。因此想要學習前端技術的人越來越多,那麼零基礎學習web ...
  • 前端開發因為其上手快,開發難度適中,而應用非常廣泛,成為目前大部分想進入IT行業的年輕人的首選。目前前端開發崗位人員主要分類三類:高校畢業生,培訓生,自學人士三大類。今天主要和大家一起來探討一下,自學前端需要掌握哪些知識點。 ...
  • Ajax 非同步 JavaScript 和 XML 第一步: 創建 XMLHttpRequest 對象,var 對象名 = new XMLHttpRequest(); Xmlhttprequest 對象用來和伺服器交換數據 第二步: XMLHttpRequest 對象的 open()和 send()方 ...
  • JavaScript箭頭函數 語法 基礎語法 高級語法 描述 引入箭頭函數有兩個方面的作用:更簡短的函數並且不綁定 this 。 更短的函數 不綁定 this 在箭頭函數出現之前,每個新定義的函數都有它自己的 this 值(在構造函數的情況下是一個新對象,在嚴格模式的函數調用中為underfined ...
一周排行
    -Advertisement-
    Play Games
  • 前言 在我們開發過程中基本上不可或缺的用到一些敏感機密數據,比如SQL伺服器的連接串或者是OAuth2的Secret等,這些敏感數據在代碼中是不太安全的,我們不應該在源代碼中存儲密碼和其他的敏感數據,一種推薦的方式是通過Asp.Net Core的機密管理器。 機密管理器 在 ASP.NET Core ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 順序棧的介面程式 目錄順序棧的介面程式頭文件創建順序棧入棧出棧利用棧將10進位轉16進位數驗證 頭文件 #include <stdio.h> #include <stdbool.h> #include <stdlib.h> 創建順序棧 // 指的是順序棧中的元素的數據類型,用戶可以根據需要進行修改 ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • C總結與剖析:關鍵字篇 -- <<C語言深度解剖>> 目錄C總結與剖析:關鍵字篇 -- <<C語言深度解剖>>程式的本質:二進位文件變數1.變數:記憶體上的某個位置開闢的空間2.變數的初始化3.為什麼要有變數4.局部變數與全局變數5.變數的大小由類型決定6.任何一個變數,記憶體賦值都是從低地址開始往高地 ...
  • 如果讓你來做一個有狀態流式應用的故障恢復,你會如何來做呢? 單機和多機會遇到什麼不同的問題? Flink Checkpoint 是做什麼用的?原理是什麼? ...
  • C++ 多級繼承 多級繼承是一種面向對象編程(OOP)特性,允許一個類從多個基類繼承屬性和方法。它使代碼更易於組織和維護,並促進代碼重用。 多級繼承的語法 在 C++ 中,使用 : 符號來指定繼承關係。多級繼承的語法如下: class DerivedClass : public BaseClass1 ...
  • 前言 什麼是SpringCloud? Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的開發便利性簡化了分散式系統的開發,比如服務註冊、服務發現、網關、路由、鏈路追蹤等。Spring Cloud 並不是重覆造輪子,而是將市面上開發得比較好的模塊集成進去,進行封裝,從 ...
  • class_template 類模板和函數模板的定義和使用類似,我們已經進行了介紹。有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同。類模板用於實現類所需數據的類型參數化 template<class NameType, class AgeType> class Person { publi ...
  • 目錄system v IPC簡介共用記憶體需要用到的函數介面shmget函數--獲取對象IDshmat函數--獲得映射空間shmctl函數--釋放資源共用記憶體實現思路註意 system v IPC簡介 消息隊列、共用記憶體和信號量統稱為system v IPC(進程間通信機制),V是羅馬數字5,是UNI ...