new運算符是JavaScript中的重要概念之一,是我們在編程、開發中經常會使用到的。在本文中,我們將從多個方面對new運算符進行詳細的講解,希望能給大家帶來更深入的理解。
一、new 運算符的基本原理
new 運算符用於創建一個實例對象,先創建一個空對象,然後調用實例對象的構造函數,將空對象作為this傳入,執行構造函數裡面的邏輯,同時this指向空對象,返回一個這個空對象的引用,這個引用就是new出來的實例對象。
下面是一個簡單的演示,展示new運算符的基本原理:
function Person(name, age) { this.name = name; this.age = age; } let person = new Person('Tom', 18); console.log(person); // Person {name: "Tom", age: 18}
在上面的例子中,我們先定義了一個構造函數 Person,然後用new運算符創建一個實例對象 person。執行 new Person(‘Tom’, 18) 時,JavaScript 引擎會先創建一個空對象,然後把這個空對象作為參數調用 Person 函數,並且在執行 Person 函數時將this指向新建的這個空對象,這樣就可以給空對象添加屬性了,最後將這個對象返回。
二、new 運算符與Object.create()的差別
很多人在理解new運算符的時候會與Object.create()搞混,這裡我們來看一下他們的區別。
Object.create()也是用來創建對象的方法,但它與new運算符不同的是,它創建的對象是以指定對象為原型創建的。這個對象的原型鏈上將會包含指定對象,如果指定對象為null,那麼它將創建一個沒有原型的對象。
下面是一個簡單的演示:
let person1 = Object.create(null); let person2 = new Object(); console.log(person1.__proto__); //undefined console.log(person2.__proto__); //{}
在上面的代碼中,我們通過Object.create(null)來創建了一個沒有原型的對象,然後通過person1.__proto__可以看到它的值為undefined;而通過new Object()創建的person2對象,它的原型鏈上包含了一個空對象{}。
三、new 運算符和構造函數
前面我們已經提到new 運算符用於創建一個實例對象,它的實際操作是先創建一個空對象,再調用實例對象的構造函數,將空對象作為this傳入,執行構造函數裡面的邏輯,同時this指向空對象,返回一個這個空對象的引用。
構造函數是用來創建對象的函數,可以帶參數,也可以不帶參數。它的內部實現邏輯就是new 運算符的邏輯,只是在「實例對象」的創建部分略有不同。構造函數在被new調用時,系統會自動創建一個空對象並將其傳入構造函數,並且在構造函數中使用的this指向這個新創建的空對象。最後,將該對象返回作為new表達式的值,從而完成了「實例對象」的創建。
function Person(name, age) { this.name = name; this.age = age; } let person = new Person("Tom", 18); console.log(person);
在上面的代碼中,我們首先定義了一個構造函數,它的作用是給每個實例對象添加一個name和age屬性。然後使用new運算符來創建一個實例對象person。
四、new 運算符與繼承
在JavaScript中,對象之間的繼承可以通過原型實現。通過定義對象的原型,可以讓這個對象從原型對象中繼承屬性和方法。可以先通過new運算符創建一個父類實例對象,再把這個實例對象作為子類的原型。這樣一來,子類就可以從父類上繼承到屬性和方法。
function Person(name, age) { this.name = name; this.age = age; } Person.prototype.sayInfo = function () { console.log("我叫" + this.name + ",我今年" + this.age + "歲"); } function Student(name, age, grade) { this.name = name; this.age = age; this.grade = grade; } Student.prototype = new Person(); let stu = new Student("Tom", 19, 1); stu.sayInfo(); // 我叫Tom,我今年19歲
在上面的例子中,我們先定義了一個構造函數Person,它有兩個屬性name和age,並且定義了一個原型上的屬性sayInfo。然後我們定義了一個構造函數Student,它繼承了Person的屬性和方法,又自己有一個屬性grade。最後通過new運算符創建了一個Student實例對象stu,調用stu.sayInfo()方法,會列印出:「我叫Tom,我今年19歲」,說明Student實例對象stu繼承了Person的sayInfo方法。
五、new 運算符和class語法
在ES6中,通過類與繼承的語法糖,我們可以更方便地定義構造函數,並且支持繼承。使用class語法糖,可以更加直觀地展示出繼承關係。
class Person { constructor(name, age) { this.name = name; this.age = age; } sayInfo() { console.log(`我叫${this.name},我今年${this.age}歲`); } } class Student extends Person { constructor(name, age, grade) { super(name, age); this.grade = grade; } } let stu = new Student("Tom", 19, 1); stu.sayInfo(); // 我叫Tom,我今年19歲
在上面的代碼中,我們通過class語法糖定義了兩個類,分別是Person和Student。Person類有兩個屬性name和age,和一個方法sayInfo。Student類繼承了Person類,並且新增了一個屬性grade。最後通過new運算符創建了一個Student實例對象stu,調用stu.sayInfo()方法,會列印出:「我叫Tom,我今年19歲」,說明Student實例對象stu繼承了Person的sayInfo方法。
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/236758.html