這篇文章主要介紹了javascript中的面向對象編程知識點,對面向對象編程進行概述,以及各種方法進行整理,感興趣的小伙伴們可以參考一下
1、面向對象的工廠方法
- 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");
- person1.sayName(); //"Nicholas"
- person2.sayName(); //"Greg"
工廠模型的方法的缺點是會產生大量重復代碼!
2、構造函數模式創建對象
- 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");
- person1.sayName(); //"Nicholas"
- person2.sayName(); //"Greg"
- alert(person1 instanceof Object); //true
- alert(person1 instanceof Person); //true
- alert(person2 instanceof Object); //true
- alert(person2 instanceof Person); //true
- alert(person1.constructor == Person); //true
- alert(person2.constructor == Person); //true
- alert(person1.sayName == person2.sayName); //false
使用new關鍵字創建對象會經歷以下四個過程
1、創建一個新對象
2、將構造函數的作用域賦給一個新對象(因此this就指向了這個新對象)
3、執行構造函數的方法(為這個新對象賦值)
4、返回新對象
3、將構造函數當函數用
- function Person(name, age, job){
- this.name = name;
- this.age = age;
- this.job = job;
- this.sayName = function(){
- alert(this.name);
- };
- }
- var person = new Person("Nicholas", 29, "Software Engineer");
- person.sayName(); //"Nicholas"
- Person("Greg", 27, "Doctor"); //adds to window
- window.sayName(); //"Greg"
- var o = new Object();
- Person.call(o, "Kristen", 25, "Nurse");
- o.sayName(); //"Kristen"
構造函數當做函數使用就和普通的函數沒有任何不同,它屬于window對象下面添加的方法而已。由于構造函數創建的對象實際上是創建一個新對象,因此在本質上兩者還是不一樣的,還是分離的,他們的方法還是不一樣的!
4、將共有的方法方法全局解決不一致的問題
- 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");
- person1.sayName(); //"Nicholas"
- person2.sayName(); //"Greg"
- alert(person1 instanceof Object); //true
- alert(person1 instanceof Person); //true
- alert(person2 instanceof Object); //true
- alert(person2 instanceof Person); //true
- alert(person1.constructor == Person); //true
- alert(person2.constructor == Person); //true
- alert(person1.sayName == person2.sayName); //true
雖然上面的方法解決了一致的問題,但是定義的全局的方法本身屬于window,那么局部和全局就沒有分開!所以這個方法使用的并不多見!也不建議使用。
5、原型模式
我們創建的任何的一個函數都有一個原型對象,這個屬性是一個指針,它指向一個對象,而這個對象的作用是可以有特定的類型的所有的實例共享的方法!
- 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); //true
- alert(Person.prototype.isPrototypeOf(person1)); //true
- alert(Person.prototype.isPrototypeOf(person2)); //true
- //only works if Object.getPrototypeOf() is available
- if (Object.getPrototypeOf){
- alert(Object.getPrototypeOf(person1) == Person.prototype); //true
- alert(Object.getPrototypeOf(person1).name); //"Nicholas"
- }
理解原型
無論什么時候只要是創建了一個函數,就會創建一個原型屬性,這個屬性指向函數的原型對象。在默認的情況下,原型對象都會包含一個constructor(構造函數屬性),這個屬性包含一個指向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();
- var person2 = new Person();
- person1.name = "Greg";
- alert(person1.name); //"Greg" 來自實例
- alert(person2.name); //"Nicholas" 來自原型
如果刪除了這個元素的實例屬性
- 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();
- var person2 = new Person();
- person1.name = "Greg";
- alert(person1.name); //"Greg" ?from instance
- alert(person2.name); //"Nicholas" ?from prototype
- delete person1.name;
- alert(person1.name); //"Nicholas" - from the prototype
6、hasOwnProperty方法
這個方法可以檢測一個屬性是否存在于實例中,還是存在于原型中!hasOwnProperty是從Object繼承來的,只要給定屬性存在于對象實例中,才會返回true.
- 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();
- var person2 = new Person();
- alert(person1.hasOwnProperty("name")); //false
- alert("name" in person1); //true
- person1.name = "Greg";
- alert(person1.name); //"Greg" ?from instance
- alert(person1.hasOwnProperty("name")); //true
- alert("name" in person1); //true
- alert(person2.name); //"Nicholas" ?from prototype
- alert(person2.hasOwnProperty("name")); //false
- alert("name" in person2); //true
- delete person1.name;
- alert(person1.name); //"Nicholas" - from the prototype
- alert(person1.hasOwnProperty("name")); //false
- alert("name" in person1); //true
7、Object.keys() 可枚舉屬性方法
這個方法接收一個對象作為參數,返回一個包含所有可枚舉屬性的字符串數組
- function Person(){
- }
- Person.prototype.name = "Nicholas";
- Person.prototype.age = 29;
- Person.prototype.job = "Software Engineer";
- Person.prototype.sayName = function(){
- alert(this.name);
- };
- var keys = Object.keys(Person.prototype);
- alert(keys); //"name,age,job,sayName"
- 如果想得到所有實例的屬性,無論它是否可以枚舉都可以使用這個方法來獲取
- function Person(){
- }
- Person.prototype.name = "Nicholas";
- Person.prototype.age = 29;
- Person.prototype.job = "Software Engineer";
- Person.prototype.sayName = function(){
- alert(this.name);
- };
- var keys = Object.getOwnPropertyNames(Person.prototype);
- alert(keys); //"constructor,name,age,job,sayName"
此方法高版本瀏覽器才支持
8、簡單的原型寫法
- function Person(){
- }
- Person.prototype = {
- name : "Nicholas",
- age : 29,
- job: "Software Engineer",
- sayName : function () {
- alert(this.name);
- }
- };
- var friend = new Person();
- alert(friend instanceof Object); //true
- alert(friend instanceof Person); //true
- alert(friend.constructor == Person); //false
- alert(friend.constructor == Object); //true
重寫了原型就等于將默認的原型方法覆蓋,那么同樣的構造方法也會被重寫,重寫的構造方法指向了Object對象!而不是原來的對象Person
如果還是想指向之前的構造方法,可以顯示的指定
- function Person(){
- }
- Person.prototype = {
- constructor : Person,
- name : "Nicholas",
- age : 29,
- job: "Software Engineer",
- sayName : function () {
- alert(this.name);
- }
- };
- var friend = new Person();
- alert(friend instanceof Object); //true
- alert(friend instanceof Person); //true
- alert(friend.constructor == Person); //true
- alert(friend.constructor == Object); //false
9、原型方法的動態添加
- function Person(){
- }
- Person.prototype = {
- constructor: Person,
- name : "Nicholas",
- age : 29,
- job : "Software Engineer",
- sayName : function () {
- alert(this.name);
- }
- };
- var friend = new Person();
- Person.prototype.sayHi = function(){
- alert("hi");
- };
- friend.sayHi(); //"hi" ?works!
10、原生對象的原型方法
- alert(typeof Array.prototype.sort); //"function"
- alert(typeof String.prototype.substring); //"function"
- String.prototype.startsWith = function (text) {//修改原生對象的原型方法
- return this.indexOf(text) == 0;
- };
- var msg = "Hello world!";
- alert(msg.startsWith("Hello")); //true
11、組合使用構造函數和原型模式創建對象
- //構造函數模式
- function Person(name, age, job){
- this.name = name;
- this.age = age;
- this.job = job;
- this.friends = ["Shelby", "Court"];
- }
- //原型模式
- Person.prototype = {
- constructor: Person,
- sayName : function () {
- alert(this.name);
- }
- };
- var person1 = new Person("Nicholas", 29, "Software Engineer");
- var person2 = new Person("Greg", 27, "Doctor");
- person1.friends.push("Van");
- alert(person1.friends); //"Shelby,Court,Van"
- alert(person2.friends); //"Shelby,Court"
- alert(person1.friends === person2.friends); //false
- alert(person1.sayName === person2.sayName); //true
12、動態原型模式
- function Person(name, age, job){
- //properties
- this.name = name;
- this.age = age;
- this.job = job;
- //methods
- if (typeof this.sayName != "function"){
- Person.prototype.sayName = function(){
- alert(this.name);
- };
- }
- }
- var friend = new Person("Nicholas", 29, "Software Engineer");
- friend.sayName();
13、寄生構造函數模式
- function Person(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 friend = new Person("Nicholas", 29, "Software Engineer");
- friend.sayName(); //"Nicholas"
- function SpecialArray(){
- //create the array
- var values = new Array();
- //add the values
- values.push.apply(values, arguments);
- //assign the method
- values.toPipedString = function(){
- return this.join("|");
- };
- //return it
- return values;
- }
- var colors = new SpecialArray("red", "blue", "green");
- alert(colors.toPipedString()); //"red|blue|green"
- alert(colors instanceof SpecialArray);
上訴方法有一點說明下,由于它是依賴外層對象來創建一個新對象,因此不能依賴 instanceof方法來確定屬性和方法的來源!它實際上和構造函數的沒有關系!
14、穩妥構造函數模式
- function Person(name, age, job){
- var o = new Object();
- o.sayName = function(){
- alert(name);
- };
- return o;
- }
- var friend = Person("Nicholas", 29, "Software Engineer");
- friend.sayName(); //"Nicholas"
此方法不依賴任何new this 關鍵符!如果要訪問對象的方法和屬性,只能通過對象已經定義好的方法來獲取!
15、繼承
javascript實現繼承是通過原型鏈來實現的
- function SuperType(){
- this.property = true;//定義一個屬性
- }
- SuperType.prototype.getSuperValue = function(){//定義的原型方法
- return this.property;
- };
- function SubType(){
- this.subproperty = false;
- }
- //inherit from SuperType
- SubType.prototype = new SuperType();
- SubType.prototype.getSubValue = function (){
- return this.subproperty;
- };
- var instance = new SubType();
- alert(instance.getSuperValue()); //true
- alert(instance instanceof Object); //true
- alert(instance instanceof SuperType); //true
- alert(instance instanceof SubType); //true
- alert(Object.prototype.isPrototypeOf(instance)); //true
- alert(SuperType.prototype.isPrototypeOf(instance)); //true
- alert(SubType.prototype.isPrototypeOf(instance)); //true
- SubType繼承SuperType的方法和屬性,因此當instance可以直接調用SuperType的方法!
- function SuperType(){
- this.property = true;
- }
- SuperType.prototype.getSuperValue = function(){
- return this.property;
- };
- function SubType(){
- this.subproperty = false;
- }
- //inherit from SuperType
- SubType.prototype = new SuperType();
- //new method
- SubType.prototype.getSubValue = function (){
- return this.subproperty;
- };
- //override existing method
- SubType.prototype.getSuperValue = function (){
- return false;
- };
- var instance = new SubType();
- alert(instance.getSuperValue()); //false
上面的例子說明,重寫的原型會覆蓋之前繼承的原型,最后返回的往往不是預期的效果
- function SuperType(){
- this.property = true;
- }
- SuperType.prototype.getSuperValue = function(){
- return this.property;
- };
- function SubType(){
- this.subproperty = false;
- }
- //inherit from SuperType
- SubType.prototype = new SuperType();
- //使用字面量添加的方法導致上面的方法失效了
- SubType.prototype = {
- getSubValue : function (){
- return this.subproperty;
- },
- someOtherMethod : function (){
- return false;
- }
- };
- var instance = new SubType();
- console.log(instance);
- alert(instance.getSuperValue()); //error!
下面的例子也說明重寫原型帶來的風險
- function SuperType(){
- this.colors = ["red", "blue", "green"];
- }
- function SubType(){
- }
- //inherit from SuperType
- SubType.prototype = new SuperType();
- var instance1 = new SubType();
- instance1.colors.push("black");
- alert(instance1.colors); //"red,blue,green,black"
- var instance2 = new SubType();
- alert(instance2.colors); //"red,blue,green,black"
原型共享導致兩個不同的對象調用的同一個數據
16、借用構造函數來實現繼承
- function SuperType(){
- this.colors = ["red", "blue", "green"];
- }
- function SubType(){
- //inherit from SuperType
- SuperType.call(this);
- }
- var instance1 = new SubType();
- instance1.colors.push("black");
- alert(instance1.colors); //"red,blue,green,black"
- var instance2 = new SubType();
- alert(instance2.colors); //"red,blue,green"
傳遞參數
- function SuperType(name){
- this.name = name;
- }
- function SubType(){
- //inherit from SuperType passing in an argument
- SuperType.call(this, "Nicholas");
- //instance property
- this.age = 29;
- }
- var instance = new SubType();
- alert(instance.name); //"Nicholas";
- alert(instance.age); //29
17、組合繼承方式
- function SuperType(name){
- this.name = name;
- this.colors = ["red", "blue", "green"];
- }
- SuperType.prototype.sayName = function(){
- alert(this.name);
- };
- function SubType(name, age){
- SuperType.call(this, name);
- this.age = age;
- }
18、原型繼承
- 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");
19、寄生組合式繼承
- function object(o){
- function F(){}
- F.prototype = o;
- return new F();
- }
- function inheritPrototype(subType, superType){
- var prototype = object(superType.prototype); //create object
- prototype.constructor = subType; //augment object
- subType.prototype = prototype; //assign object
- }
- function SuperType(name){
- this.name = name;
- this.colors = ["red", "blue", "green"];
- }
- SuperType.prototype.sayName = function(){
- alert(this.name);
- };
- function SubType(name, age){
- SuperType.call(this, name);
- this.age = age;
- }
- inheritPrototype(SubType, SuperType);
- SubType.prototype.sayAge = function(){
- alert(this.age);
- };
- var instance1 = new SubType("Nicholas", 29);
- instance1.colors.push("black");
- alert(instance1.colors); //"red,blue,green,black"
- instance1.sayName(); //"Nicholas";
- instance1.sayAge(); //29
- var instance2 = new SubType("Greg", 27);
- alert(instance2.colors); //"red,blue,green"
- instance2.sayName(); //"Greg";
- instance2.sayAge(); //27
以上就是今天的javascript學習小結,之后每天還會繼續更新,希望大家繼續關注。
新聞熱點
疑難解答
圖片精選