《JavaScript高級程式設計》筆記:面向對象的程式設計(六)

来源:https://www.cnblogs.com/moqiutao/archive/2018/12/12/10107293.html
-Advertisement-
Play Games

面向對象的語言有一個標誌,那就是它們都有類的概念,而通過類可以創建任意多個具有相同屬性和方法的對象。 理解對象 創建自定義對象的最簡單的方法就是創建一個Object的實例,然後再為它添加屬性和方法。例如: 同樣上面的例子可以通過對象字面量語法寫成如下: 屬性類型 ECMAScript中有兩種屬性:數 ...


面向對象的語言有一個標誌,那就是它們都有類的概念,而通過類可以創建任意多個具有相同屬性和方法的對象。

理解對象

創建自定義對象的最簡單的方法就是創建一個Object的實例,然後再為它添加屬性和方法。例如:

var person = new Object();
    person.name="Nicholas";
    person.age=29;
    person.job="Software Engineer";
    person.SayName=function(){
        alert(this.name);
    }

同樣上面的例子可以通過對象字面量語法寫成如下:

var person ={
        name:"Nicholas",
        age:29,
        person.job:"Software Engineer",
        SayName:function(){
            alert(this.name);
        }
    }

屬性類型

ECMAScript中有兩種屬性:數據屬性和訪問器屬性。

1.數據屬性

數據屬性包含一個數據值的位置。在這個位置可以讀取和寫入值。數據屬性有四個描述其行為的特性。

Configurable:表示能否通delete刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為訪問器屬性。像前面的例子中那樣直接在對象上定義屬性,它們的這個特性預設值為true。

Enumerable:表示能否通過for-in迴圈返回屬性。像前面的例子中那樣直接在對象上定義屬性,它們的這個特性的預設值為true。

Writable:表示能否修改屬性的值。前面例子直接在對象上定義的屬性,它們的這個特性預設值為true。

Value:包含這個屬性的數據值。讀取屬性值的時候,從這個位置讀;寫入屬性值的時候,把新值保存到這個位置。這個特性預設值為undefined。

對於前面的例子,value特性被設置為特定的值。例如:

var person={
    name="Niceholas"
}

這裡創建一個名為name的屬性,為它指定的值是"Niceholas"。也就是說value特性將被設置為"Niceholas",而對這個值的任何修改都將反映在這個位置。

要修改屬性預設的特性,必須使用ECMAScript5的Object.defineProperty()方法。這個方法接收三個參數:屬性所在的對象、屬性名字和一個描述符對象。其中,描述符對象的屬性必須是Configurable、Enumerable、Writable、Value。設置其中的一或多個值。可以修改對應的特性值。例如:

var person={};
    Object.defineProperty(person,"name",{
        writable:false,
        value:'Nich'
    });
    
    alert(person.name);//Nich
    person.name="Greg";
    alert(person.name);//Nich

這個例子創建了一個名為name的屬性,它的值為Nich是只讀的。這個屬性的值是不可以修改的,如果嘗試為它指定新值,則在非嚴格模式下,賦值操作將被忽略;在嚴格模式下,賦值操作將會拋出錯誤。
類似的規則也適用與不可配置的屬性。例如:

var person={};
    Object.defineProperty(person,"name",{
        configurable:false,
        value:'Nich'
    });
    
    alert(person.name);//Nich
    delete person.name;
    alert(person.name);//Nich
    
    

註意:一旦把屬性定義為不可配置的,就不能再把它變回可配置了。此時,再調用Object.defineProperty()方法修改除了writable之外的特性,都會導致錯誤。

var person={};
    Object.defineProperty(person,"name",{
        configurable:false,
        value:'Nich'
    });

    //拋出錯誤
    Object.defineProperty(person,"name",{
        configurable:true,
        value:'Nich'
    });
    

也就是說,多次調用Object.defineProperty()方法修改同一個屬性,但是把configurable特性設置為false之後就會有限制了。
在調用Object.defineProperty()方法時,如果不指定,configurable、Enumerable和writable特性的預設值為false。多數情況下,可能都沒有必要利用Object.defineProperty()方法提供的這些高級功能。不過,理解這些概念對於理解javascript對象卻非常有用。

註:IE8是第一個實現Object.defineProperty()方法的瀏覽器版本。然而,這個版本的實現存在諸多的限制:只能在DOM對象上使用這個方法,而且只能創建訪問器屬性。由於實現不徹底,建議不要在IE8中使用Object.defineProperty()方法。

2.訪問器屬性
訪問器屬性不包含數據值;它們包含一對兒getter和setter函數(不過,這兩個函數都不是必需的)。

在讀取訪問器屬性時,會調用getter函數,這個函數負責返回有效的值;在寫入訪問器屬性時,會調用setter函數並傳入新值,這個函數負責決定如何處理數據。訪問器屬性有如下4個特性。

  • [Configurable]:表示能否通過delete刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為數據屬性。對於直接在對象上定義的屬性,這個特性的預設值為true。
  • [Enumerable]:表示能否通過for-in迴圈返回屬性。對於直接在對象上定義的屬性,這個特性預設值為true。
  • [Get]:在讀取屬性時調用的函數。預設值為undefined。
  • [Set]:在寫入屬性時調用的函數。預設值為undefined。

訪問器屬性不能直接定義,必須使用Object.defineProperty()來定義。下麵例子:

var book={
        _year:2004,
        edition:1
    }
    Object.defineProperty(book,"year",{
        get:function(){
            return this._year;
        },
        set:function(newValue){
            console.log(newValue);
            if(newValue>2004){
                this._year=newValue;
                this.edition+=newValue-2004;
            }
        }
    });
    book.year=2005;
    console.log(book.edition);//2

//上面代碼創建了一個book對象,並給它定義兩個預設的屬性:_year和edition。_year前面的下劃線是一種常用的記號,用於表示只能通過對象方法訪問的屬性。


//支持ECMAScript5的這個方法的瀏覽器有IE9+、Firefox4+、SaFari5+、Opera12+和Chrome。在這個方法之前,要創建訪問器屬性,一般都使用兩個非標準的方法:__defineGetter__()和__defineSetter__()。這2個方法最初是由Firefox引入的,後來SaFari3、Chrome1、opera9.5也給出了相同的實現。使用這2個遺留的方法,可以實現上面的例子如下:
var book={
    _year:2004,
    edition:1
}
//定義訪問器的舊有方法
book.__defineGetter__('year',function(){
    return this._year;
});
book.__defineSetter__('year',function(newValue){
    if(newValue>2004){
        this._year=newValue;
        this.edition+=newValue-2004;
    }
});
book.year=2005;
alert(book.edition);//2

在不支持Object.defineProperty()方法的瀏覽器中不能修改[Configurable] 和[Enumerable]。

定義多個屬性

ECMAScript5又定義了一個Object.defineProperties()方法。這個方法接收兩個對象參數:第一個對象是要添加和修改其屬性的對象;第二個對象的屬性與第一個對象中添加或修改的屬性一一對應。例如:

var book={}

Object.defineProperties(book,{

    _year:{
        value:2004
    },
    edition:{
        value:1
    },
    year:{

        get:function(){
            return this._year;
        },
        set:function(newValue){
            if(newValue>2004){
                this._year=newValue;
                this.edition+=newValue-2004;
            }
        }
    }
})

讀取屬性的特性

使用Object.getOwnPropertyDescriptor()方法,這個方法接收兩個參數:屬性所在的對象和要讀取的屬性名稱。

var book={};
Object.defineProperties(book,{

    _year:{
        value:2004
    },
    edition:{
        value:1
    },
    year:{

        get:function(){
            return this._year;
        },
        set:function(newValue){
            if(newValue>2004){
                this._year=newValue;
                this.edition+=newValue-2004;
            }
        }
    }
})

var descriptor=Object.getOwnPropertyDescriptor(book,'_year');
alert(descriptor.value);//2004
alert(descriptor.configurable);//false
alert(typeof descriptor.get);//undefined

var descriptor=Object.getOwnPropertyDescriptor(book,'year');
alert(descriptor.value);//undefined
alert(descriptor.configurable);//false
alert(typeof descriptor.get);//'function'

創建對象

雖然object構造函數或對象字面量都可以用來創建單個對象。但這些方式有個明顯的缺點:使用同一個介面創建很多對象,會產生大量重覆代碼。

工廠模式

function createPerson(name, age,job){
    var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function(){
        alert(this.name);
    }

    return o;
}

var person1 = createPerson("Nicholas", 29, "Software Engineer");
var person2 = createPerson("Greg", 27, "Doctor");

工廠模式雖然解決了創建多個相似對象的問題,但卻沒有解決對象識別的問題(即怎樣知道一個對象的類型)。

構造函數模式

function Person(name, age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function(){
        alert(this.name);
    }
   
}

var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");

從上面的例子可以看出,要創建一個Person實例,需要使用new操作符。以這種方式調用構造函數要經歷下麵四個步驟:

  • 創建一個新對象;
  • 將構造函數的作用域賦給新對象(因此this就指向了這個新對象);
  • 執行構造函數中的代碼(為這個新對象添加屬性);
  • 返回新對象。

前面生成的兩個person1和person1對象實例,這兩個對象都一constructor屬性,該屬性指向Person,如下代碼:

console.log(person1.constructor == Person); //true
console.log(person2.constructor == Person); //true

對象的constructor屬性最初是用來標識對象類型的。但是,提到檢測對象類型,使用instanceof操作符更可靠些。我們在上面創建的person1,person2對象既是Object的實例,同時也是Person的實例。

console.log(person1 instanceof Person); //true
console.log(person1 instanceof Object); //true
console.log(person2 instanceof Person); //true
console.log(person2 instanceof Object); //true

1.將構造函數當函數
例如前面例子中的Person函數可以用下麵任何一種方式調用:

//當成構造函數使用
var person1 = new Person("Nicholas", 29, "Software Engineer");
person1.sayName();//Nicholas
//作為普通函數調用
Person("Greg", 27, "Doctor");
window.sayName();//Greg 


//在另一個對象的作用域中調用
var o=new Object();
Person.call(o,"Kristen",25,"Nurse");
o.sayName();
    

2.構造函數的問題

function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = new Function("console.log(this.name)"); // 與聲明函數在邏輯上是等價的
}

以這種方法創建函數,會導致不同的作用域鏈和標示符解析。不同實例上的同名函數是不相等的。

var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");
console.log(person1.sayName == person2.sayName); // false  

然後,創建兩個完成同樣任務的Function實例的確沒有必要;況且有this對象在,根本不用在執行代碼前就把函數綁定到特定對象上面。因此,大可像下麵這樣,通過把函數定義轉移到構造函數外部來解決這個問題。

function Person(name, age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = sayName;
}

function sayName(){
    alert(this.name);
}

var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");

可是新問題又來了:在全局作用域中定義的函數實際上只能被某個對象調用,這讓全局作用域有點名不副實。而更讓人無法接受的是:如果對象需要定義很多方法,那麼就要定義很多多個全局函數,於是我們這個自定義的引用類型就絲毫沒有封裝性可言了。好在,這些問題可以通過使用原型模式來解決。

原型模式

我們創建的每個函數都有一個prototype(原型)屬性,這個屬性是一個指針,指向一個對象,而這個對象的用途是包含可以由特定類型的所有實例共用的屬性和方法。也就是說prototype就是通過調用構造函數而創建的那個實例對象的原型對象。

function Person(){}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software  Engineer";
Person.prototype.sayName = function(){
    alert(this.name);
}

var person1 = new Person();
person1.sayName(); // Nicholas

var person2 = new Person();
person2.sayName(); // Nicholas
alert(person1.sayName == person2.sayName);

從圖上可以看到構造函數Person的屬性prototype指向了函數的原型對象,這個原型對象剛開始只有一個constructor屬性,後面給它添加了原型對象的屬性和方法。person1和person2的實例對象沒有標準的方式訪問[[prototype]],但firefox,safari,chrome在每個對象上有一個內部屬性__proto__;這個內部屬性__proto__指向了Person.prototype。這兒說明下,Person.prototype.constructor == Person為true,說明Person.prototype.constructor指回了Person。

isPrototypeOf()

console.log(Person.prototype.isPrototypeOf(person1)); // true
console.log(Person.prototype.isPrototypeOf(person2)); // true

hasOwnProperty()

function Person(){}

Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software  Engineer";
Person.prototype.sayName = function(){
    console.log(this.name);
}

var person1 = new Person();
var person2 = new Person();

console.log(person1.hasOwnProperty("name")); // false

person1.name = "Greg";
console.log(person1.name); // Greg
console.log(person1.hasOwnProperty("name")); // true

console.log(person2.name); // Nicholas
console.log(person2.hasOwnProperty("name")); // false

delete person1.name;
console.log(person1.name); // Nicholas
console.log(person1.hasOwnProperty("name")); // false

原型與in操作符

function Person(){}

Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software  Engineer";
Person.prototype.sayName = function(){
    console.log(this.name);
}

var person1 = new Person();
var person2 = new Person();

console.log(person1.hasOwnProperty("name")); // false
console.log("name" in person1); // true

person1.name = "Greg";
console.log(person1.name); // Greg
console.log(person1.hasOwnProperty('name')); // true
console.log("name" in person1); // true


console.log(person2.name); // Nicholas
console.log(person2.hasOwnProperty('name')); // false
console.log("name" in person2); // true

delete person1.name;
console.log(person1.name); // Nicholas
console.log(person1.hasOwnProperty('name')); // false
console.log("name" in person1); // true

同時使用hasOwnProperty()方法和in操作符,就可以確定該屬性到底是存在於對象中,還是存在於原型中,如下:

function hasPrototypeProperty(object,name){
    return !object.hasOwnProperty(name)&&(name in object);
}

只要in操作符返回true而hasOwnProperty()返回false,就可以確定屬性是原型中的屬性。

更簡單的原型語法

function Person(){}

Person.prototype = {
    name: "Nicholas", 
    age:29,
    job: "Software Engineer",
    sayName: function(){
        console.log(this.name);
    }
}

var friend = new Person();
console.log(friend instanceof Object); // true
console.log(friend instanceof Person); // true
console.log(friend.constructor == Person); // false
console.log(friend.constructor == Object); // true

如果constructor的值真的很重要,可以像下麵這樣特意將它設置回適當的值。

function Person(){}

Person.prototype = {
    constructor: Person,
    name: "Nicholas", 
    age:29,
    job: "Software Engineer",
    sayName: function(){
        console.log(this.name);
    }
}

原型對象的問題

function Person(){}

Person.prototype = {
    constructor: Person,
    name: "Nicholas", 
    age:29,
    job: "Software Engineer",
    friends: ['Shelby', "Court"],
    sayName: function(){
        console.log(this.name);
    }
}

var person1 = new Person();
var person2 = new Person();

person1.friends.push("Van");

console.log(person1.friends); //Shelby,Court,Van
console.log(person2.friends); //Shelby,Court,Van
console.log(person1.friends===person2.friends); // true

假如我們的初衷就是像這樣在所有實例中共用一個數組,那麼對這個結果無話可說。可是,實例一般都是要有屬於自己的全部屬性的。而這個問題正是我們很少看到有人單獨使用原型模式的原因所在。

組合使用構造函數模式和原型模式

function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["Shelby", "Court"];
}

Person.prototype = {
    constructor: Person,
    sayName: function(){ console.log(this.name);}
}

var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor");

person1.friends.push("Van");
console.log(person1.friends); // Shelby, Count, Van
console.log(person2.friends); // Shelby, Count
console.log(person1.friends === person2.friends); // false
console.log(person1.sayName === person2.sayName); // true

在這個例子中,實例屬性都是在構造函數中定義的,而由所有實例共用的屬性constructor和方法sayName()則是在原型中定義的。這種構造函數與原型混成的模式,是目前認同度最高的一種創建自定義類型的方法。

動態原型模式

function Person(name, age,job){
    this.name = name;
    this.age = age;
    this.job = job;
}

if (typeof this.sayName!='function'){
    Person.prototype.sayName = function(){
        console.log(this.name);
   }
}

var friend = new Person("Nicholas",29,"Software Engineer");
friend.sayName(); //Nicholas

寄生構造函數模式

這種模式的基本思想是創建一個函數,這個函數的作用僅僅是封裝創建對象的代碼,然後返回新創建的對象。

function Person(name,age,job){
    var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function(){
        console.log(this.name);
    };
    return o;
}

var friend = new Person("Nicholas", 29, "Software Engineer");
friend.sayName(); // Nicholas

關於寄生構造函數模式,返回的對象與構造函數或者構造函數的原型屬性之間沒有關係;也就是說,構造函數返回的對象與在構造函數外部創建的對象沒有什麼不同。

 function SpecialArray(){
        var values=new Array();
        values.push.apply(values,arguments);
        values.toPipedString=function(){
            return this.join("|");
        }
        return values;
    }
    var colors=new SpecialArray("red","blue","green");
    console.log(colors.toPipedString()); //red|blue|green
    

穩妥構造函數模式

所謂穩妥對象,指的是沒有公共屬性,而且其方法也不引用this的對象。

其特點是:一是新創建的對象實例方法不引用this;二是不使用new操作符調用構造函數。

把前面的Person構造函數重新如下:

function Person(name,age,job){
    var o = new Object();
    
   //可以在這兒創建私有變數和函數
   //方法
    o.sayName = function(){
        console.log(name);
    };
    
    //返回對象
    return o;
}

var friend = Person("Nicholas", 29, "Software Engineer");
friend.sayName(); // Nicholas

繼承

原型鏈

function SuperType(){
     this.property= true;
}

SuperType.prototype.getSuperValue = function(){
    return this.property;
};

function Subtype(){
    this.subproperty = false;
}

// 繼承了SuperType
Subtype.prototype = new SuperType();

Subtype.prototype.getSubValue = function(){
    return this.subproperty;
}

var instance = new Subtype();
console.log(instance.getSuperValue()); // true

謹慎地定義方法

function SuperType(){
     this.property= true;
}

SuperType.prototype.getSuperValue = function(){
    return this.property;
};

function Subtype(){
    this.subproperty = false;
}

// 繼承了SuperType
Subtype.prototype = new SuperType();

Subtype.prototype = {
    getSubValue: function(){
        return this.subproperty;
    },
    someOtherMethod: function(){
        return false;
    }
};

var instance = new Subtype();
console.log(instance.getSuperValue()); // error

原型鏈的問題

包含引用類型值的原型屬性會被所有實例共用;而這也正是為什麼要在構造函數中,而不是在原型對象中定義屬性的原因。
在創建子類型的實例時,不能向超類型的構造函數中傳遞參數。實際上,應該說是沒有辦法在不影響所有對象實例的情況下,給超類型的構造函數傳遞參數。

function SuperType(){
    this.colors = ["red", "blue", "green"];
}

function Subtype(){
    
}
Subtype.prototype= new SuperType();
var instance1 = new Subtype();
instance1.colors.push("black");
console.log(instance1.colors); // red, blue, green, black

var instance2 = new Subtype();
console.log(instance2.colors); // red, blue, green, black

借用構造函數

1.傳遞參數

function SuperType(name){
    this.name = name;
}

function Subtype(){
    SuperType.call(this,"Nicholas");
    this.age = 29;
}

var instance = new Subtype();
console.log(instance.name); //Nicholas
console.log(instance.age); // 29

2.借用構造函數的問題

方法都在構造函數中定義,因此函數復用就無從談起。而且在超類型的原型中定義的方法,在子類型中就無法調用了。

組合繼承

function SuperType(name){
    this.name = name;
    this.colors = ["red", "blue", "green"];
}

SuperType.prototype.sayName = function(){
    console.log(this.name);
};

function Subtype(name,age){
    SuperType.call(this,name);
    this.age = age;
}

Subtype.prototype = new SuperType();
Subtype.prototype.sayAge = function(){
   console.log(this.age);
};

var instance1 = new Subtype("Nicholas", 29);
instance1.colors.push("black");
console.log(instance1.colors); // red, blue, green, black
instance1.sayName(); // Nicholas
instance1.sayAge(); //29

var instance2 = new Subtype("Greg", 2);
console.log(instance2.colors); // red, blue, green
instance2.sayName(); // Greg
instance2.sayAge(); //2

組合繼承避免了原型鏈和借用函數的缺陷,融合了它們的優點,成為Javascript中最常用的繼承模式。

原型式繼承

function object(o){
    function F(){}
    F.prototype = o;
    return new F();
}
var person = {
    name:"Nicholas",
    friends:["Shelby", "Court", "Van"]
};

var anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");

var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");

console.log(person.friends); // Shelby, Court, Van, Rob, Barbie

Object.create()

Object.create()方法規範了原型式繼承。

var person = {
    name:"Nicholas",
    friends:["Shelby", "Court", "Van"]
};

var anotherPerson = Object.create(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");

var yetAnotherPerson = Object.create(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");

console.log(person.friends); // Shelby, Court, Van, Rob, Barbie

寄生式繼承

function object(o){
    function F(){}
    F.prototype = o;
    return new F();
}

function inheritPrototype(subType,superType){
    var prototype = object(superType.prototype);
    prototype.constructor = subType;
    subType.prototype = prototype;
}

function SuperType(name){
    this.name = name;
    this.colors = ["red", "blue", "green"];
}

SuperType.prototype.sayName = function(){
    console.log(this.name);
}

function Subtype(name,age){
    SuperType.call(this,name);
    this.age = age;
}

inheritPrototype(Subtype, SuperType);

Subtype.prototype.sayAge = function(){
    console.log(this.age);
}

 


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

-Advertisement-
Play Games
更多相關文章
  • 最近的一個項目中的需求要對一堆元素進行排序,排序的依據是元素在頁面上面的坐標位置,然後按照順序給所有元素一個編號。如下圖所示: 排序並編號 排序並編號 做這個需求的是一個新入職的小伙,思考摸索了很久,他也沒有找到合適的方法。不得不說,部分新入職的小伙的思維能力還是有待提高啊。其實這個問題很簡單,就是 ...
  • JavaScript是運行在客戶端的腳本,因此一般是不能夠設置Session的,因為Session是運行在伺服器端的。 而cookie是運行在客戶端的,所以可以用JS來設置cookie. 假設有這樣一種情況,在某個用例流程中,由A頁面跳至B頁面,若在A頁面中採用JS用變數temp保存了某一變數的值, ...
  • 本文由雲+社區發表 本文主要講述瞭如何一步步在生產環境上部署django和vue,操作系統預設為centos 說明 :後文中出現的以下字元串均表示具體的路徑或者名稱,含義如下: DJANGO_DIR 表示django的工程根目錄 DJANGO_NAME 表示django的工程名稱 VUE_HTML_ ...
  • Collapse 摺疊面板源碼: collapse.vue collapse item.vue ...
  • 嗷嗷方便的文字轉語音,不過用的時候記得到百度語音上申請key,免費的.之前在網路上看到有人寫了一部分,自己豐富下,以後用也方便 ...
  • 來自:https://blog.csdn.net/m0_37068028/article/details/72898154 侵刪 來自:https://segmentfault.com/a/1190000010378259 侵刪 第一種: //date.jsexport function forma ...
  • tofixed方法 四捨五入 toFixed() 方法可把 Number 四捨五入為指定小數位數的數字。例如將數據Num保留2位小數,則表示為:toFixed(Num);但是其四捨五入的規則與數學中的規則不同,使用的是銀行家舍入規則,銀行家舍入:所謂銀行家舍入法,其實質是一種四舍六入五取偶(又稱四舍 ...
  • 示例html代碼: 示例html代碼: 示例html代碼: 示例html代碼: 示例html代碼: <div id="test"> <span style="color:red">test1</span> test2 </div> 獲得id為test的DOM對象,下麵就不一一獲取了。 var tes ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...