這篇文章主要介紹了關於js中自訂物件的解析,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下
一、物件
# 1.字面量建立物件
var person = { name: "sun", age: 18, work: function () { console.log(this.name + "is working..."); }, address: { home: "大屯里xxx路xxx小区xx单元xxx室", phone: "123456789", } }; person.work(); console.log(person.address.home);
2.資料描述與存取描述設定
var person = { age: 18, address: { home: "大屯里xxx路xxx小区xx单元xxx室", phone: "123456789", } }; Object.defineProperties(person, { name: { value: "sun", // 该属性的值,可被读取 writable: true, // 表示能否修改属性的值,默认值为true configurable: true, // 表示能否delete该属性并重新定义,直接在对象上定义的属性默认值为true enumerable: true // 表示能否通过for-in枚举,直接在对象上定义的属性默认值为true }, work: { value: function(){ console.log(this.name + "is working..."); }, // 通过Object.defineProperty和Object.defineProperties定义属性, // 如果没有声明writable、configurable、enumerable,它们的默认值都是false } }); person.work(); console.log(person.address.home);
3.get和set
var circle = { value: 10, get girth(){ return 2 * 3.14 * this.R }, get area(){ return 3.4 * this.R * this.R }, }; Object.defineProperty(circle, "R", { get : function () { return this.value; }, set : function (val) { console.log("半径被修改了!"); this.value = val; } }); circle.R = 100; console.log("girth: " + circle.girth + "area: " + circle.area);
4.資料描述與存取描述檢查
var circle = { R: 10, // __proto__: null, get area(){ return 3.4 * this.R * this.R }, }; Object.defineProperty(circle, "site", { value: [0, 2.2, 4.1], // enumerable: true, // 是否可配置(读取),不设置为true时,Object.keys(circle))和Object.values(circle))将获取不到该键值对 }); console.log("R" in circle); // 检查属性 console.log(circle.hasOwnProperty("R")); // 检查自有的属性 console.log(circle.propertyIsEnumerable("R")); // 检查属性是否是可枚举的 // Object对象的方法 console.log(Object.keys(circle)); console.log(Object.values(circle)); console.log(Object.getOwnPropertyNames(circle)); // 检查对象自身所有属性 console.log(Object.getOwnPropertyDescriptor(circle, "R")); // 得到circle对象关于R属性的描述
二、prototype
1.prototype釋義
- 每一次创建函数,解析器都会向函数中添加一个属性:prototype - 如果函数作为普通函数调用prototype,没有任何作用 - 当该函数以构造函数的形式调用时,它会有一个隐含的属性__proto__指向其原型对象 - 每个实例有各自的__proto__指向原型对象的prototype, 也就是原型对象中的属性和方法被调用函数"共享" - 当类的原型对象prototype指向的内存地址发生改变时,已创建实例的__proto__ !== prototype,也就是不会被覆盖。而新创建的实例仍然是__proto__ === prototyp
function Person(name, age) { this.name = name; this.age = age; } // Person.prototype.gender = "male"; // Person.prototype.sayHello = function () { // return this.name + ", " + this.age + "years old." // }; Person.prototype = { gender: "male", sayHello: function () { return this.name + ", " + this.age + "years old." } }; var p1 = new Person("孙悟空", 2000); p1.sayHello(); console.log(Person.prototype); console.log(Person.prototype.constructor === Person);
2.prototype與__proto__
function Person() {} var obj1 = { gender: "male"}; // 创建两个内存地址 var obj2 = { age: 200 }; Person.prototype = obj1; var p1 = new Person(); console.log(p1.__proto__ === Person.prototype); console.log(p1.__proto__.gender); console.log(Person.prototype); Person.prototype = obj2; var p2 = new Person(); console.log(p2.__proto__.age); console.log(Person.prototype); console.log(p1.__proto__.age); // undefined console.log(p2.__proto__.gender); // undefined console.log(p1.__proto__ === Person.prototype); // false,表示当prototype指向的内存地址改变时,已经创建的实例对象的__proto__仍指向原来的内存地址 console.log(p2.__proto__ === Person.prototype);
function Person() {} Person.prototype = {name: "xxx", age: 100,}; var p1 = new Person(); console.log(p1.__proto__.name); Person.prototype = { price: 998,}; var p2 = new Person(); console.log(p2.__proto__.price); console.log(p1.__proto__.price); // undefined console.log(p2.__proto__.name); // undefiend console.log(p1.__proto__ === Person.prototype); // false, 原型对象的内存地址引用已发生改变 console.log(p1.__proto__.age); // __proto__指向的内存地址被保留 console.log(p2.__proto__ === Person.prototype); // true
function Person() {} Person.prototype = { price: 60 }; var p1 = new Person(); Person.prototype = { price: 998}; var p2 = new Person(); console.log(p1.__proto__ === Person.prototype); // 依然是false console.log(p2.__proto__ === Person.prototype); // true
3.prototype之共享性
// prototype非常类似python中的静态属性和静态方法。每个实例都可以访问同一块内存空间。 function Person() {} Person.prototype = {price: 60}; var p1 = new Person(); var p2 = new Person(); console.log(p1.__proto__.price); console.log(p2.__proto__.price); console.log(Person.prototype.price);
4.prototype#之繼承性
// 当访问实例对象的一个属性或方法时,它会先在对象自身中查找,如果有则直接使用;如果没有则在原型对象中继续查找,如果有则直接使用 function Person() {} Person.prototype = {price: 60}; var p1 = new Person(); var p2 = new Person(); console.log(p1.price); console.log(p2.price); console.log(Person.prototype.price);
三、類別
1.類別的封裝
// 字面量方法(工厂方法) -- 直接在var obj = {}内部写代码,缺点是只实例化一次 // 构造函数方法 -- 只用构造函数声明this,缺点是可扩展性差,数据重复 // 原型方法 -- 只用prototype声明共有的属性和方法,缺点是实例的数据相同,不满足多态
1.混合的建構子/原型方法
// 最广泛的使用方法 function Person(name, age) { this.name = name; this.age = age; } // prototype写在外面是为了保证其动态增加公共属性和方法 Person.prototype.sayHello = function () { console.log(this.name + ", " + this.age + " years old."); // 把共有的属性和方法封装到prototype中 }; var p = new Person("孙悟空", 2000); p.sayHello();
// 我把它写给Person的属性,让父类也能够访问 function Person(name, age) { Person.group = Person.prototype.group = "西天取经组"; Person.toString = Person.prototype.toString = function (){ console.log("Person: " + Person.group) }; this.name = name; this.age = age; this.sayHello = function () { console.log(this.name + ", " + this.age + "years old.") }; } var person = new Person("孙悟空", 2000); console.log(person.constructor); // 检查构造器函数 console.log(person instanceof Person); // 检查是否为其原型类 person.sayHello(); Person.toString();
2.動態原型方法
// 也是常用的方法 function Person(name, age) { this.name = name; this.age = age; if (typeof Person._initialized === "undefined"){ Person.prototype.sayHello = function () { console.log(this.name + ", " + this.age + " years old."); }; Person._initialized = true; } } var p = new Person("孙悟空", 2000); p.sayHello();
3.混合工廠方法
// 混合工厂方法 -- 存在与工厂方法类似的问题,不建议使用 function Person(name, age) { var obj = {}; obj.name = name; obj.age = age; obj.sayHello = function () { console.log(this.name + ", " + this.age + " years old."); }; return obj } var p = new Person("孙悟空", 2000); p.sayHello();
4.再探討類別結構
function Person(name, age) { // 静态属性 Person.group = "西天取经四人组,暗合金木水火土"; // 静态方法 Person.introduce = function () { console.log("贫僧自东土大唐而来") }; // 实例属性 this.name = name; this.age = age; // 实例方法,应该写在prototype中 this.say = function () { console.log("hello, i'm " + this.name); }; Person.prototype.introduce = Person.introduce; // 此时Person类和其实例都可以使用introduce方法 // 父类使用实例方法 Person.example = Person.prototype.example = function (self) { self = self || this; console.log(self.name + " " + self.age); } } // 在python中,实例可以访问父类的属性和方法,父类也可以使用实例方法 // 在java和js中,实例不能调用父类的静态属性和静态方法,父类不能使用实例方法 // 如果想让实例和父类共享一个属性或者方法,就只能放到方法区并创建引用 var sun = new Person("孙悟空", 2000); Person.introduce(); // 父类调用静态方法 sun.say(); sun.introduce(); // 实例调用静态方法 Person.example(sun); // 父类调用实例方法 sun.example(); // 子类调用实例方法 // 可见,prototype是父类和实例的沟通桥梁
2.自訂類別
function Person(name, age) { this.name = name; this.age = age; this.sayHello = function () { console.log(this.name + ", " + this.age + "years old.") }; } function New(Person) { return function () { var obj = {"__proto__": Person.prototype}; // 必须写在这里 Person.apply(obj, arguments); // arguments同this一样,是默认自带的关键字,用于存储传入的参数 return obj } } var temp = New(Person); var p1 = temp("孙悟空", 2000); var p2 = temp("猪八戒", 1); p1.sayHello(); p2.sayHello();
3.類別的繼承
1.拷貝傳承量物件(實例)
var person = { name: "Li", age: 16, address: { home: "none", city: "none", }, say: function(){ console.log("hello, guy.") } }; var child = {gender:"female",}; function extendDeeply (p, c){ var c = c || {}; for (var prop in p) { if (typeof p[prop] === "object") { c[prop] = (p[prop].constructor === Array) ? [] : {}; extendDeeply(p[prop], c[prop]); } else { c[prop] = p[prop]; } } } extendDeeply(person, child); console.log(child); child.say();
2.call與apply實作物件繼承
function Person(name, age) { this.name = name; this.age = age; this.address = { home: "none", city: "none", } } Person.prototype.say = function () { console.log("hello, guy.") }; // 它继承的只是实例对象this,无法继承父类原型prototyp function Child(name, age) { Person.call(this, name, age); this.gender = "female"; } var child = new Child("Li", 16); console.log(child); // child.say(); 报错: child.say is not a function.
对象继承的缺点:只继承了实例对象的可访问的属性和方法,没有继承原型
3.原型鏈繼承
// 原型链继承 function Person() {} Person.prototype.name = "Person"; Person.prototype.toString = function () { console.log(this.name); }; function Child(name, age) { this.age = age; this.name = name; } Child.prototype = Person.prototype; Child.prototype.constructor = Child; var child = new Child("Li", 16); console.log(child.name + " " + child.age); child.toString(); // 其缺点是之继承了原型,没有继承实例
4.create實作類別繼承
function Person(name, age) { this.name = name; this.age = age; this.address = { home: "none", city: "none", } } Person.prototype.say = function () { console.log("hello, guy.") }; function Child(P, name, age) { function F() {} F.prototype = new P(name, age); var c = new F(); return c; } Child.prototype.constructor = Child; // 无法修正 var child = new Child(Person, "Li", 16); console.log(child); console.log(child.name); child.say(); console.log(child.constructor); // 结果为[Function: Person],构造器指向无法修正 console.log(child instanceof Child); // false console.log(child instanceof Person); // true
5.Object.create實作類別繼承 -- 建議的方式
// Object.create继承,实现原理和上面的create类似 // 1.创建父类 function Person() {} Person.prototype.sayPerson = function () { console.log("hello, Person.") }; // 2.创建子类 function Child(gender) {this.gender = gender;} // 3.create继承 // Object.create的第二个参数是属性描述 Child.prototype = Object.create(Person.prototype, { name: { value: "Li", writable: true, enumerable: true, configurable: true, }, age: { value: 16, writable:true, configurable:true, enumerable:true, }, }); // 重写子类prototype Child.prototype.constructor = Child; // constructor 修正 // 4.在create之后写子类的prototype Child.prototype.sayChild = function () { console.log("hello, Child.") }; var child = new Child("female"); console.log(child); console.log(child.name + " " + child.age); child.sayChild(); child.sayPerson();
5.組合繼承-- 建議的方式
function Person(name, age) { this.name =name; this.age = age; } Person.prototype.toString = function () { console.log(this.name + " " + this.age); }; function Child(name, age, gender) { Person.call(this, name, age); this.gender = gender; } Child.prototype = new Person(); // new时不传参数,是为了只继承原型,即Child.prototype = Person.prototype // Child.prototype = Person.prototype; // 两者等价 Child.prototype.constructor = Child; var child = new Child("Li", 16, "female"); console.log(child); child.toString(); console.log(child instanceof Child); // true console.log(child instanceof Person); // true
6.繼承總結
rr]# 7. prototype、constructor和__proto__在繼承中的關係
#以上就是本文的全部內容,希望對大家的學習有所幫助,更多相關內容請關注PHP中文網!
相關建議:
以上是js中自訂物件的解析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

Python更适合数据科学和机器学习,JavaScript更适合前端和全栈开发。1.Python以简洁语法和丰富库生态著称,适用于数据分析和Web开发。2.JavaScript是前端开发核心,Node.js支持服务器端编程,适用于全栈开发。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

禪工作室 13.0.1
強大的PHP整合開發環境

SublimeText3 Linux新版
SublimeText3 Linux最新版

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

記事本++7.3.1
好用且免費的程式碼編輯器

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。