JavaScript學習總結(二)——閉包、IIFE、apply、函數與對象

来源:http://www.cnblogs.com/best/archive/2016/12/21/6206268.html
-Advertisement-
Play Games

一、閉包(Closure) 1.1、閉包相關的問題 請在頁面中放10個div,每個div中放入字母a-j,當點擊每一個div時顯示索引號,如第1個div顯示0,第10個顯示9;方法:找到所有的div,for迴圈綁定事件。 示例代碼: 運行結果: 因為點擊事件的函數內部使用外部的變數i一直在變化,當我 ...


一、閉包(Closure)

1.1、閉包相關的問題

請在頁面中放10個div,每個div中放入字母a-j,當點擊每一個div時顯示索引號,如第1個div顯示0,第10個顯示9;方法:找到所有的div,for迴圈綁定事件。

示例代碼:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>閉包</title>
        <style type="text/css">
            div {
                width: 100px;
                height: 100px;
                background: lightgreen;
                float: left;
                margin: 20px;
                font: 30px/100px "microsoft yahei";
                text-align: center;
            }
        </style>
    </head>
    <body>
        <div>a</div>
        <div>b</div>
        <div>c</div>
        <div>d</div>
        <div>e</div>
        <div>f</div>
        <div>g</div>
        <div>h</div>
        <div>i</div>
        <div>j</div>
        <script type="text/javascript">
            var divs=document.getElementsByTagName("div");
            for (var i=0;i<divs.length;i++) {
                divs[i].onclick=function(){
                    alert(i);
                }
            }
        </script>
    </body>
</html>

運行結果:

因為點擊事件的函數內部使用外部的變數i一直在變化,當我們指定click事件時並沒有保存i的副本,這樣做也是為了提高性能,但達不到我們的目的,我們要讓他執行的上下文保存i的副本,這種機制就是閉包。

修改後的代碼:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>閉包</title>
        <style type="text/css">
            div {
                width: 100px;
                height: 100px;
                background: lightgreen;
                float: left;
                margin: 20px;
                font: 30px/100px "microsoft yahei";
                text-align: center;
            }
        </style>
    </head>
    <body>
        <div>a</div>
        <div>b</div>
        <div>c</div>
        <div>d</div>
        <div>e</div>
        <div>f</div>
        <div>g</div>
        <div>h</div>
        <div>i</div>
        <div>j</div>
        <script type="text/javascript">
            var divs=document.getElementsByTagName("div");
            for (var i=0;i<divs.length;i++) {
                divs[i].onclick=(function(n){
                    return function(){
                        alert(n);    
                    }
                })(i);
            }
        </script>
    </body>
</html>

運行結果:

n是外部函數的值,但是內部函數(點擊事件)需要使用,返回函數前的n被臨時駐留在記憶體中給點擊事件使用,簡單說就是函數的執行上下文被保存起來,i生成了多個副本。

1.2、理解閉包

閉包概念:當一個內部函數被調用,就會形成閉包,閉包就是能夠讀取其他函數內部變數的函數,定義在一個函數內部的函,創建一個閉包環境,讓返回的這個子程式抓住i,以便在後續執行時可以保持對這個i的引用。內部函數比外部函數有更長的生命周期;函數可以訪問它被創建時所處的上下文環境。

Javascript語言特有的"鏈式作用域"結構(chain scope),子對象會一級一級地向上尋找所有父對象的變數

二、對象

對象就是“鍵/值”對的集合併擁有一個連接到原型(prototype)對隱藏連接。

2.1、對象常量(字面量)

一個對象字面量就是包含在一對花括弧中的零個或多個“鍵/值”對。對象字面量可以出現在任何允許表達式出現的地方。

對象的定義:

        //空對象
        var obj1={};
        
        //對象中的屬性
        var obj2={name:"foo",age:19};
        var obj3={"nick name":"dog"};
        
        //對象中的方法
        var obj4={
            price:99,
            inc:function(){
                this.price+=1;
            }
        }

對象中可包含的內容:

對象常量可以出現在任何允許表達式出現的地方,對象、數組、函數可以相互間嵌套,形式可以多種多樣。對象的值可以是:數組,函數,對象,基本數據類型等。

            //對象中可包含的內容
            var obj5 = [{
                name: "jack"
            }, {
                name: "lucy",  //常量
                hobby:["讀書","上網","代碼"],  //數組
                friend:{name:"mark",height:198,friend:{}},  //對象
                show:function(){  //函數
                    console.log("大家好,我是"+this.name);
                }
            }];
            //對象中的this是動態的,指向的是:調用者
            obj5[1].show();

輸出:大家好,我是lucy

2.2、取值

方法一:直接使用點號運算

            //3取值
            var obj6={"nick name":"pig",realname:"Rose"};
            console.log(obj6.realname);
            //console.log(obj6.nick name);  錯誤

方法二:使用索引器,當對象中的key有空格是

            //3取值
            var obj6={"nick name":"pig",realname:"Rose"};
            
            console.log(obj6["realname"]);
            console.log(obj6["nick name"]);

2.3、枚舉(遍歷)

方法一:

            var obj7={weight:"55Kg","nick name":"pig",realname:"Rose"};
            
            for (var key in obj7) {
                console.log(key+":"+obj7[key]);
            }

運行結果:

輸出順序是不能保證的。

2.4、更新與添加

如果對象中存在屬性就修改對應值,如果不存在就添加。對象通過引用傳遞,它們永遠不會被覆制

            var obj8={realname:"King"};
            obj8.realname="Queen";  //修改
            obj8.weight=1000;  //添加屬性
            obj8.show=function()  //添加方法
            {
                console.log(this.realname+","+this.weight);
            }
            obj8.show();

輸出:

Queen,1000

            var obj8={realname:"King"};
            obj8.realname="Queen";  //修改
            obj8.weight=1000;  //添加屬性
            obj8.show=function()  //添加方法
            {
                console.log(this.realname+","+this.weight);
            }
            obj8.show();
            
            //引用
            var obj9=obj8;   //obj9指向obj8的引用
            obj9.realname="Jack";
            obj8.show();

輸出:

2.5、對象的原型

javascript是一種動態語言,與C#和Java這樣的靜態語言是不一樣的;javascript並沒有嚴格的類型,可以簡單認為javascript是由對象組成的,對象間連接到原型(prototype)實現功能的擴展與繼承。每個對象都鏈接到一個原型對象,並且可以從中繼承屬性,所有通過常量(字面量)創建的對象都連接到Object.prototype,它是JavaScript中的頂級(標配)對象,類似高級語言中的根類。

現在我們修改系統中的Object對象,添加一個創建方法,指定要創建對象的原型,實現類似繼承功能:

        <script type="text/javascript">
            if(typeof Object.beget !== "function")
            {
                Object.create = function(o) {
                    //構造函數,用於創建對象
                    var F = function() {};
                    //指定由構造函數創建的對象的原型
                    F.prototype = o;
                    //調用構造方法創建新對象
                    return new F();
                }
            }
            
            var rose={
                name:"rose",
                show:function(){
                    console.log("姓名:"+this.name);
                }
            };
            
            rose.show();  //輸出
            
            var lucy=Object.create(rose);  //簡單認為是:創建一個對象且繼承rose
            lucy.name="lucy";  //重寫
            lucy.show();
        </script>

運行結果:

原型關係是一種動態關係,如果修改原型,該原型創建的對象會受到影響。

            var lucy=Object.create(rose);  //簡單認為是:創建一個對象且繼承rose
            lucy.name="lucy";  //重寫
            
            var jack=Object.create(rose);
            jack.name="jack";
            
            //修改原型中的方法
            rose.show=function(){
                console.log("姓名->"+this.name);
            }
            
            lucy.show();
            jack.show();

結果:

關於原型在函數中會再講到。

2.6、刪除

            //刪除屬性
            delete mark.name;   
            //調用方法,輸出:姓名:undefined
            mark.show(); 
            
            //刪除函數
            delete mark.show;  
            //錯誤,mark.show is not a function
            mark.show();

刪除不用的屬性是一個好習慣,在某些情況下可能引發記憶體泄漏。

2.7、封裝

使用對象封裝的好處是可以減少全局變數的污染機會,將屬性,函數都隸屬一個對象。

封裝前:

var name="foo";   //name是全局的,被暴露
            i=1;  //全局的,沒有var關鍵字聲明的變數是全局的,與位置關係不大
            function show(){  //show 是全局的,被暴露
                console.log("name->"+name);
                console.log(++i);
            }
            
            //i是全局的 2
            show();  
            //3
            show();

封裝後:

//對外只暴露bar,使用閉包封裝
            var bar=function(){
                var i=1;
                return{
                    name:"bar",
                    show:function(){
                        console.log("name->"+this.name);
                        console.log(++i);
                    }
                };
            };
            
            var bar1=bar();
            //2
            bar1.show();
            //3
            bar1.show();
            
            var bar2=bar();
            //2,因為被封裝,且閉包,i是局部私有的
            bar2.show();

運行結果:

三、函數

javascript中的函數就是對象,對象就是“鍵/值”對的集合併擁有一個連接到原型對隱藏連接。

3.1、參數對象 (arguments)

第一個函數中有一個預設對象叫arguments,類似數組,但不是數組,該對象是傳遞給函數的參數。

        <script type="text/javascript">
            function counter(){
                var sum=0;
                for(var i=0;i<arguments.length;i++){
                    sum+=arguments[i];
                }
                return sum;
            }
            
            console.log(counter(199,991,1,2,3,4,5));
            console.log(counter());
        </script>

運行結果:

1205

這裡的arguments是一個隱式對象,不聲明也在函數中,內部函數可以訪問外部函數的任意內容,但是不能直接訪問外部函數的arguments與this對象。

            function f1()
            {
                console.log(arguments.length);
                f2=function()
                {
                    console.log(arguments.length);
                }
                return f2;
            }
            
            var f=f1(1,2,3);
            f();

運行結果:

3

0

3.2、構造函數

在javascript中對象構造函數可以創建一個對象。

           <script type="text/javascript">
           /*構造函數*/
          //可以簡單的認為是一個類型的定義
           function Student(name,age){
                 this.name=name;
                 this.age=age;
                 this.show=function(){
                     console.log(this.name+","+this.age);
                 }
           }
           
           //通過new關鍵字調用構造函數,創建一個對象tom
           var rose=new Student("rose",18);
           var jack=new Student("jack",20);
           
           rose.show();
           jack.show();
        </script>

3.3、函數調用

3.3.1、call

調用一個對象的一個方法,以另一個對象替換當前對象

call([thisObj[,args])

hisObj 可選項。將被用作當前對象的對象。args 將被傳遞方法參數序列。
call 方法可以用來代替另一個對象調用一個方法。call 方法可將一個函數的對象上下文從初始的上下文改變為由 thisObj 指定的新對象。

示例:

           /*構造函數*/
           function Student(name,age){
                 this.name=name;
                 this.age=age;
           }
           
            show=function(add){
                     console.log(add+":"+this.name+","+this.age);
               }
           
           //通過new關鍵字調用構造函數,創建一個對象tom
           var rose=new Student("rose",18);
           var jack=new Student("jack",20);
          
          //調用show方法,指定上下文,指定調用對象,this指向rose,“大家好是參數”
          show.call(rose,"大家好");
          show.call(jack,"Hello");

運行結果:

call方法中的參數都可以省去,第1個參數表示在哪個對象上調用該方法,或this指向誰,如果不指定則會指向window對象。

示例:

          var name="無名";
          var age=18;
          show.call();

結果:

undefined:無名,18

3.3.2、apply

apply([thisObj[,argArray]])
應用某一對象的一個方法,用另一個對象替換當前對象,與call類似。
如果 argArray 不是一個有效的數組或者不是arguments對象,那麼將導致一個 TypeError。
如果沒有提供 argArray 和 thisObj 任何一個參數,那麼 Global 對象將被用作 thisObj, 並且無法被傳遞任何參數。
對於第一個參數意義都一樣,但對第二個參數:
apply傳入的是一個參數數組,也就是將多個參數組合成為一個數組傳入,而call則作為call的參數傳入(從第二個參數開始)。
如 func.call(func1,var1,var2,var3)對應的apply寫法為:func.apply(func1,[var1,var2,var3])
同時使用apply的好處是可以直接將當前函數的arguments對象作為apply的第二個參數傳入

示例代碼:

           /*構造函數*/
           function Student(name,age){
                 this.name=name;
                 this.age=age;
           }
           
            show=function(greeting,height){
                     console.log(greeting+":"+this.name+","+this.age+","+height);
               }
           
           //通過new關鍵字調用構造函數,創建一個對象tom
           var rose=new Student("rose",18);
           var jack=new Student("jack",20);
          
          //調用show方法,指定上下文,指定調用對象,this指向rose,“大家好是參數”
          show.apply(rose,["大家好","178cm"]);
          show.apply(jack,["Hello","188cm"]);

運行結果:

 

從上面的示例中可以發現apply的第2個參數是一個數組,數組中的內容將映射到被調用方法的參數中,如果單這樣看發現不如call方便,其實如果直接取方法的參數arguments則apply要方便一些。通過簡單的變化就可以替代call。

          function display(){
             show.apply(jack,arguments);
          }
          display("hi","224cm");

結果:

hi:jack,20,224cm

javascript里call和apply操作符可以隨意改變this指向
如果在javascript語言里沒有通過new(包括對象字面量定義)、call和apply改變函數的this指針,函數的this指針都是指向window的。
關於this指針,我的總結是:是誰調用的函數,那麼這個函數中的this指針就是它;如果沒有明確看出是誰調用的,那麼應該就是window調用的,那麼this指針就是window。

3.3.3、caller

在一個函數調用另一個函數時,被調用函數會自動生成一個caller屬性,指向調用它的函數對象。如果該函數當前未被調用,或並非被其他函數調用,則caller為null。
在JavaScript的早期版本中,Function對象的caller屬性是對調用當前函數的函數的引用

        function add()
        {
            console.log("add被調用");
            //add方法的調用函數,如果調用add方法的不是函數則為null
            console.log(add.caller);
        }
        
        function calc(){
            add();
        }
        
        //直接調用add方法
        add(); 
        //間接通過calc方法調用
        calc();

運行結果:

caller與this還是有區別的,this是指調用方法的對象,而caller是指調用函數的函數。

        <script type="text/javascript">
        function add(n)
        {
            console.log("add被調用");
            if(n<=2){
                return 1;
            }
            return add.caller(n-1)+add.caller(n-2);
        }
        
        function calc(n){
            console.log("calc被調用");
            return add(n);
        }
        
        //1 1 2
        console.log(calc(3));
        </script>

結果:

3.3.4、Callee

當函數被調用時,它的arguments.callee對象就會指向自身,也就是一個對自己的引用

           function add(n1,n2){
                  console.log(n1+n2);
                  //arguments.callee(n1,n2);  //指向add方法
                  return arguments.callee;
           }
           
           add(1,2)(3,4)(5,6)(7,8)(8,9);

運行結果:

當第1次調用add方法時輸入3,立即將函數返回再次調用,每次調用後又返回自己,這樣可以實現鏈式編程。

3.5、立即執行函數表達式 (IIFE)

IIFE即Immediately-Invoked Function Expression,立即執行函數表達式

3.5.1、匿名函數與匿名對象

匿名函數就是沒有名稱的函數,javascript中經常會使用匿名函數實現事件綁定,回調,實現函數級的私有作用域,如下所示:

        function(){
            console.log("這是一個匿名函數");
        };

匿名對象:

        {
            name:"foo",
            show:function(){
                console.log(this.name);
            }
        }

沒有名稱的匿名函數也叫函數表達式,它們間是有區別的。

3.5.2、函數與函數表達式

下麵是關於函數與函數表達式定義時的區別

a)、函數定義(Function Declaration)

function Identifier ( Parameters ){ FunctionBody }

function 函數名稱(參數){函數主體}

在函數定義中,參數(Parameters)標識符(Identifier )是必不可少的。如果遺漏,會報提示錯誤:

代碼:

        function(){
            console.log("這是一個匿名函數");
        };

 

結果:

b)、函數表達式(Function Expression)

function Identifier(Parameters){ FunctionBody }
函數表達式中,參數和標識符都是可選的,與函數定義的區別是標識符可省去。

其實,"function Identifier(Parameters){ FunctionBody }"並不是一個完整的函數表達式,完整的函數的表達式,需要一個賦值操作。
比如: var name=function Identifier(Parameters){ FunctionBody }

3.5.3、立即執行函數表達式與匿名對象

            //1 正常定義函數
            function f1(){
                console.log("正常定義f1函數");
            };
            
            //2 被誤解的函數表達式
            function(){
                console.log("報錯Unexpected token (");
            }();
            
            //3 IIFE,括弧中的內容被解釋成函數表達式
            (function(){
                console.log("IIFE,正常執行");
            })();
            
            //4 函數表達式
            var f2=function(){
                console.log("這也被視為函數表達式");
            };

第3種寫法為什麼這樣就能立即執行並且不報錯呢?因為在javascript里,括弧內部不能包含語句,當解析器對代碼進行解釋的時候,先碰到了(),然後碰到function關鍵字就會自動將()裡面的代碼識別為函數表達式而不是函數聲明。

如果需要將函數表達式或匿名對象立即執行,可以使用如下方法:

<!DOCTYPE html>
<html>

    <head>
        <meta charset="UTF-8">
        <title>IIFE</title>
    </head>

    <body>
        <script type="text/javascript">
            //調用匿名函數
            (function() {
                console.log("這是一個函數表達式");
            })();

            //調用匿名對象
            ({
                name: "foo",
                show: function() {
                    console.log(this.name);
                }
            }).show();

            console.log({
                a: 1
            }.a);

            console.log({
                a: function() {}
            }.a());
        </script>
    </body>

</html>

運行結果:

3.5.4、各種IIFE的寫法

//最常用的兩種寫法
(function(){ /* code */ }()); // 老師推薦寫法
(function(){ /* code */ })(); // 當然這種也可以

// 括弧和JS的一些操作符(如 = && || ,等)可以在函數表達式和函數聲明上消除歧義
// 如下代碼中,解析器已經知道一個是表達式了,於是也會把另一個預設為表達式
// 但是兩者交換則會報錯
var i = function(){ return 10; }();
true && function(){ /* code */ }();
0, function(){ /* code */ }();

// 如果你不怕代碼晦澀難讀,也可以選擇一元運算符
!function(){ /* code */ }();
~function(){ /* code */ }();
-function(){ /* code */ }();
+function(){ /* code */ }();

// 你也可以這樣
new function(){ /* code */ }
new function(){ /* code */ }() // 帶參

如果是函數表達式,可直接在其後加"()"立即執行。

如果是函數聲明,可以通過"()"、"+"、"-"、"void"、"new"等運算符將其轉換為函數表達式,然後再加"()"立即執行。

3.5.5、參數

函數表達式也是函數的一種表達形式,同樣可以像函數一樣使用參數,如下所示:

            (function (n){
                console.log(n);
            })(100);

輸出:100 

其實通過IIFE還能形成一個類似的塊級作用域,當塊內的程式在使用外部對象時將優先查找塊內的對象,再查找塊外的對象,依次向上。

            (function(win,undfd){
                win.console.log("Hello"==undfd);
            })(window,undefined);

3.5.6、添加分號

為了避免與其它的javascript代碼產生影響後報錯,常常會在IIFE前增加一個分號,表示前面所有的語句都結束了,開始新的一語句。

            var k=100
            (function (n){
                console.log(n);
            })(k);

上面的腳本會報錯,因為javascript解釋器會認為100是函數名。

            var k=100
            ;(function (n){
                console.log(n);
            })(k);

 

這樣就正確了,在javascript中一行語句的結束可以使用分號,也可以不使用分號,因為一般的自定義插件會使用IIFE,這是一段獨立的代碼,在應用過程中不能保證用戶會加上分號,所以建議在IIFE前加上分號。

3.5.7、IIFE的作用

1)、提高性能

減少作用域查找時間。使用IIFE的一個微小的性能優勢是通過匿名函數的參數傳遞常用全局對象window、document、jQuery,在作用域內引用這些全局對象。JavaScript解釋器首先在作用域內查找屬性,然後一直沿著鏈向上查找,直到全局範圍。將全局對象放在IIFE作用域內提升js解釋器的查找速度和性能。

function(window, document, $) {

}(window, document, window.jQuery); 

2)、壓縮空間

通過參數傳遞全局對象,壓縮時可以將這些全局對象匿名為一個更加精簡的變數名

function(w, d, $) {  
  
}(window, document, window.jQuery);

3)、避免衝突

 匿名函數內部可以形成一個塊級的私有作用域。

4)、依賴載入

可以靈活的載入第三方插件,當然使用模塊化載入更好(AMD,CMD),示例如下。

A.html與B.html文件同時引用公用的common.js文件,但是只有A.html需要使用到StuObj對象,B.html不需要,但使用其它方法。

Student.js

var StuObj = {
    getStu: function(name) {
        return new Student(name);
    }
}

/*構造函數*/
function Student(name) {
    this.name = name;
    this.show = function() {
        console.log("Hello," + this.name);
    }
}

Common.js

function other1() {}

function other2() {}

(function($) {
    if($) {
        $.getStu("Tom").show();
    }
})(typeof StuObj=="undefined"?false:StuObj);

A.HTML

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>A</title>
    </head>
    <body>
        <script src="js/Student.js" type="text/javascript" charset="utf-8"></script<

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

-Advertisement-
Play Games
更多相關文章
  • 一、概述 橋接模式:將兩個原本不相關的類結合在一起,然後利用兩個類中的方法和屬性,輸出一份新的結果。 二、案例 1、模擬毛筆(轉) 需求:現在需要準備三種粗細(大中小),並且有五種顏色的比 如果使用蠟筆,我們需要準備3*5=15支蠟筆,也就是說必須準備15個具體的蠟筆類。而如果使用毛筆的話,只需要3 ...
  • 第一是:項目的路徑需要放在Documents and Settings\,也就是預設的文件夾的地方,不然會報錯錯誤範例為:Question:CY8CKIT-023 kit example project fails to build in PSoC Creator with the followin ...
  • 我使用的是海康DS-2CD852MF-E, 200萬,網路攝像機,已經比較老了,不過SDK在海康官網下載的,開發流程都差不多. 海康攝像機回調解碼後的視頻數據格式為YV12,順便說一下YV12的數據格式 YYYY V U. 我這個是720P,即1280 * 720解析度. 那麼Y分量的數量為 128 ...
  • 適配器模式:將一個類的介面轉換成客戶希望的另外一個介面,使得原本由於介面不相容而不能一起工作的那些類可以在一起工作。 如下圖(借圖): // 設置書的介面 客戶端測試: 輸出結果: 這時候,你想創建一個可以復用的類,該類可以與其他不相關的類或不可預見的類(即那些介面可能不一定相容的類)協同工作。 如 ...
  • 這節主要說一下Angular的指令。Angular的指令有內置指令和自定義指令。 一、內置指令 在 Angular 中通過指令對DOM的功能進行擴展。這也是對常用功能的模塊化封裝。Angular 提供了一系列常用的指令,這些指定都是以 ng 開頭的,我們稱為內置指令。 後面會講到如何自定義指令。其實 ...
  • TYPESDK 服務端設計思路與架構之一:應用場景分析 作為一個渠道SDK統一接入框架,TYPESDK從一開始,所面對的需求場景就是多款游戲,通過一個統一的SDK服務端,能夠同時接入幾十個甚至幾百個各種渠道的SDK。而且這些渠道介面的具體接入欄位和接入邏輯,每個月以至每周,都可能發生或大或小的變動。 ...
  • 好久沒寫代碼了,終於好不容易接到了開發任務,一看時間還挺充足的,我就慢慢整吧,若是遇上趕進度,基本上直接是功能優先,完全不考慮設計。你可以認為我完全沒有追求,當身後有鞭子使勁趕的時候,神馬設計都是浮雲,按時上線才是王道,畢竟領導是不會關註過程和代碼質量的,領導只看結果,這也許就是我等天朝碼農的悲哀。 ...
  • datepicker可以為bootstrap添加一個事件選擇控制項,適用於任何需要調用的場合,支持多種事件格式輸出(比如:dd, d, mm, m, yyyy, yy等),是製作網頁不可缺失的插件。 Requirements Bootstrap 2.0.4+ jQuery 1.7.1+ 線上文檔 Da ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...