日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

如何写一个作用域安全的构造函数

發(fā)布時(shí)間:2023/12/2 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何写一个作用域安全的构造函数 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

基礎(chǔ)部分

構(gòu)造函數(shù)本質(zhì)上就是一個(gè)使用new操作符調(diào)用的函數(shù),使用new調(diào)用時(shí),構(gòu)造函數(shù)內(nèi)用到的this對(duì)象會(huì)指向新創(chuàng)建的對(duì)象實(shí)例:

function Girlfriend(name, age, height) {this.name = name;this.age = age;this.height = height; }// 使用new操作符來(lái)分配這些屬性 var girlfriend = new Girlfriend("Ying", 23, 170);

平時(shí)寫(xiě)變量時(shí),如果因?yàn)槭д`忘記使用new操作符時(shí),會(huì)造成一個(gè)糟糕的影響————因?yàn)閠his對(duì)象是在運(yùn)行時(shí)綁定的,直接調(diào)用構(gòu)造函數(shù),this會(huì)映射到全局對(duì)象window上,導(dǎo)致錯(cuò)誤對(duì)象屬性的增加,增添不必要的變量到全局對(duì)象中:

var girlfriend = new Girlfriend("Ying", 23, 170); console.log(window.name); // "Ying" console.log(window.age); // 23 console.log(window.height); // 170

特別的,當(dāng)你自己構(gòu)造函數(shù)內(nèi)的某些變量名與window變量名重名時(shí)(像一些常用變量名name、length等),對(duì)這些屬性的偶然覆蓋就很可能導(dǎo)致其他地方出錯(cuò),并且這個(gè)bug還相當(dāng)難找!

在這種情況下構(gòu)造一個(gè)作用域安全的構(gòu)造函數(shù)就顯得很有必要:

function Girlfriend(name, age, height) {// 首先確認(rèn)this對(duì)象是正確類型的實(shí)例,// 如果不是就創(chuàng)建新的實(shí)例并返回if (this instanceof Girlfriend) { // 添加一個(gè)檢查console.log('created');this.name = name;this.age = age;this.height = height;} else {console.log('new');return new Girfriend(name, age, height);} }var girlfriend1 = Girlfriend("Ying", 23, 170); // "new" "created" console.log(window.name); // "" console.log(girfriend1.name); // "Ying"var girlfriend2 = new Girlfriend("Lin", 22, 165); // "created" console.log(girfriend1.name); // "Lin"

girlfriend1背后構(gòu)造函數(shù)先new了一個(gè)實(shí)例并返回實(shí)例(打印“new”),再對(duì)實(shí)例進(jìn)行賦值(打印“created”)。
girlfriend2自己就先new了一個(gè)實(shí)例,直接對(duì)該實(shí)例進(jìn)行賦值(只打印“created”)。

這樣在任何情況下就都可以返回一個(gè)安全作用域的實(shí)例了。

進(jìn)階部分

使用上面添加一個(gè)檢查的方法可以創(chuàng)建一個(gè)作用域安全的構(gòu)造函數(shù),但如果有的函數(shù)竊取該函數(shù)的繼承且沒(méi)有使用原型鏈,那這個(gè)繼承將被破壞不生效:

function Bmi(sex, weight=1, height=1) { // ES6開(kāi)始支持的默認(rèn)值if (this instanceof Bmi) {this.sex = sex;this.weight = weight;this.height = height;this.getBmi = function() {return this.weight / (this.height ** 2);};} else {return new Bmi(sex);} }function People(height, weight) {Bmi.call(this, 'male');this.height = height;this.weight = weight; }var guy = new People(1.75, 68); // 單位是m和kg console.log(guy.sex) // undefined

Bmi構(gòu)造函數(shù)作用域是安全的,但People并不是。新創(chuàng)建一個(gè)People實(shí)例后,這個(gè)實(shí)例準(zhǔn)備通過(guò)Bmi.call()來(lái)繼承Bmi的sex屬性,但由于Bmi的作用域是安全的,this對(duì)象并非是Bmi的實(shí)例,所以Bmi會(huì)先自己創(chuàng)建一個(gè)新的Bmi對(duì)象,不會(huì)把新的Bmi對(duì)象的值傳遞到People中去。

這樣People中的this對(duì)象并沒(méi)有得到增長(zhǎng),同時(shí)Bmi.call()返回的值也沒(méi)有用到,所以People實(shí)例中就不會(huì)有sex、weight、height屬性和getBmi()函數(shù)。

解決辦法: 構(gòu)造函數(shù)結(jié)合使用原型鏈或寄生組合:

function Bmi(sex, weight=1, height=1) {if (this instanceof Bmi) {this.sex = sex;this.weight = weight;this.height = height;this.getBmi = function() {return this.weight / (this.height ** 2);};} else {return new Bmi(sex);} }function People(height, weight) {Bmi.call(this, 'male');this.height = height;this.weight = weight; }People.prototype = new Bmi(); // 重點(diǎn)var guy = new People(1.75, 68); console.log(guy.sex) // "male"

這樣寫(xiě)的話,一個(gè)People的實(shí)例同時(shí)也是一個(gè)Bmi的實(shí)例,所以Bmi.call()才會(huì)去執(zhí)行,為People實(shí)例添加上屬性和函數(shù)。

總結(jié)

當(dāng)多個(gè)人一同構(gòu)建一個(gè)項(xiàng)目時(shí),作用域構(gòu)安全函數(shù)就非常必要,對(duì)全局對(duì)象意外的更改可能就會(huì)導(dǎo)致一些常常難以追蹤的錯(cuò)誤,這和平常設(shè)置空變量和空函數(shù)一樣避免因?yàn)槠渌丝赡馨l(fā)生的錯(cuò)誤而阻塞程序執(zhí)行。


更多專業(yè)前端知識(shí),請(qǐng)上 【猿2048】www.mk2048.com

總結(jié)

以上是生活随笔為你收集整理的如何写一个作用域安全的构造函数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。