讀書筆記-你不知道的JS上-混入與原型

繼承

?

mixin混合繼承

    function mixin(obj1, obj2) {for (var key in obj2) {//重復不復制if (!(key in obj1)) {obj1[key] = obj2[key];}}return obj1;}

  這種復制是淺復制,對象或者數組函數等都是同一個引用,改變obj1的會同時影響obj2。

?

寄生繼承

  ...

?

隱式繼承

  子類調用fn.call(this)

?

  深拷貝需要重新聲明一個變量(對象),遍歷(遞歸)復制,詳情見我的函數技巧,不貼出來了。

?

?

原型

  Javascript對象中有一個特殊的[[prototype]]內置屬性,其實就是對于其他對象的引用。幾乎所有的對象在創建時[[prototype]]屬性都會被賦予一個非空的值。

    var f = {a: 1};// 創建一個對象 原型為fvar f2 = Object.create(f);// 通過原型鏈找到了屬性aconsole.log(f2.a);

  使用for..in遍歷對象的原理和原型鏈類似,任意可枚舉在原型鏈上的屬性都會被遍歷。使用in操作符檢查屬性時也會查找對象原型鏈,無論是否可枚舉。

  所有普通對象的原型最終指向Object.prototype。

  詳細講解一個對象賦值語句:

    var obj = {};obj.a = 1;

  這里有四種情況:

  1、obj中存在a屬性,就會被修改。

    var obj = {a: 2};obj.a = 1;console.log(obj.a); //1

  2、obj的原型鏈不存在a屬性,就會被直接添加到obj上。

    var obj = {};console.log('a' in obj); //falseobj.a = 1;console.log(obj.a); //1

  3、obj與obj的原型鏈都存在a屬性,就會發生屏蔽,obj中的a會屏蔽原型鏈上的a。

    var obj2 = {a: 2};var obj = Object.create(obj2);obj.a = 1;console.log(obj.a); //1

  4、obj的原型鏈上存在a屬性,而obj不存在時,會出現多種情況。

  在原型鏈上存在a屬性且沒有被標記為只讀,那就會直接在obj添加一個a屬性。(情況3)

  在原型鏈上存在a屬性且被標記為只讀,那么無法創建該屬性,嚴格模式會報錯,普通模式賦值語句會被忽略。

    // 在'use strict'模式下// Cannot assign to read only property 'a' of object '#<Object>'var obj2 = {};Object.defineProperty(obj2, 'a', {value: 2,configurable: true,enumerable: true,writable: false})var obj = Object.create(obj2);obj.a = 1; //無效console.log(obj.a); //2

  如果在原型鏈上存在a并且它是一個setter,那就一定會調用這個setter。a不會被添加到obj,也不會重新定義setter。

    var obj2 = {set a(val) {console.log(1);}};var obj = Object.create(obj2);obj.a = 1; // 執行set并輸出1

  如果希望怎么樣都添加屬性,請使用Object.defineProperty(...)。

?

關于prototype

  所有函數默認都會擁有一個名為prototype的公有不可枚舉屬性,它會指向另外一個對象:

    function fn() {console.log(1);}console.log(fn.prototype); //Object{}

?

  這個對象通常被稱為fn的原型,實際上不如叫fn.prototype。

    function fn() {console.log(1);}var f = new fn();console.log(f.__proto__ === fn.prototype); //true

  在調用new fn()時,會創建一個對象,并給一個內部[[prototype]]鏈接,連接到fn.prototype。個人感覺__proto__這個瀏覽器私有實現的屬性叫原型比較好,畢竟原型鏈是通過這個屬性向上查找的。

  實際上,new操作符實際上并沒有直接創建關聯,這只是一個副作用。

  通過Object.create()方法才是正規創建原型鏈接的方法。

  上一段代碼很容易讓人認為fn是一個構造函數,因為這里用new來調用它并構造出一個對象。

  實際上,fn和普通的函數沒有區別。函數本身不是構造函數,當在普通的函數前面加上new時,就會把這個函數調用變成了一個‘構造函數調用’。實際上,new會劫持所有普通函數并用構造形式來調用它。

  

  考慮下面一段代碼。

    function fn(a) {this.a = a;}fn.prototype.getA = function() {return this.a;}var f1 = new fn(1);var f2 = new fn(2);console.log(f1.getA()); //1console.log(f2.getA()); //2

?  這段代碼展示了兩種面向類的技巧:

  1、this.name=name給每個對象都綁定了.name屬性。

  2、fn.prototype.getA=...給原型添加了一個方法,現在,每一個實例都可以調用getA方法。

  看起來,似乎創建f1、f2時會把對象復制到這兩個新對象中,然而實際上只是通過原型鏈向上查找調用了方法而已。

?

關于constructor

    function fn1() {};var f1 = new fn1();console.log(f1.constructor === fn1); //true//替換默認原型function fn2() {};fn2.prototype = {};var f = new fn2();console.log(f.constructor === fn2); //falseconsole.log(f.constructor === Object); //true

  當前用新對象替換fn原型時,new出來的新對象不會自動獲得constructor屬性。所以,不能說因為f.constructor===fn屬性,就認為fn構造了對象f。

  實際上,new出來的對象f并沒有.constructor屬性,它會委托原型去查找該屬性,默認的原型(fn.prototype)有construtor屬性并且指向fn,所以f.constructor(實際上調用的是fn.prototype.constructor)會指向fn。但是如果替換了fn.prototype,新的原型對象并不會默認有.construtor,于是委托會一直提交到Object.prototype,恰好Object.prototype.constructor===Object,結果也在上面代碼中展示出來了。

  可以手動給新原型添加constructor屬性:

    function fn2() {};fn2.prototype = {};fn2.prototype.constructor = fn2; //修正原型鏈var f = new fn2();console.log(f.constructor === fn2); //trueconsole.log(f.constructor === Object); //false

  看,修復了!(實際上應該用Object.defineProperty來定義constructor,因為該屬性應該是不可枚舉的)

  所以說,constructor并不是一個不可變屬性,它只是默認不可枚舉,但是值可以被任意修改。

?

原型繼承

  常見誤用形式和正確使用方式:

    function fn1() {};function fn2() {};//不可以 只是復制引用//fn1.prototype = fn2.prototype;//可以實現 但是會執行fn2函數 可能出現額外問題//fn1.prototype=new fn2;//ES6前 需要拋棄fn1默認的prototype 可能還要修正constructor屬性fn1.prototype = Object.create(fn2.prototype);//ES6語法 直接修正默認prototypeObject.setPrototypeOf(fn1.prototype, fn2.prototype);

  

  如何找出任意對象的原型鏈呢?有一個方法是instanceof。

    function fn() {}var f = new fn;console.log(f instanceof fn); //true

  instanceof操作符左邊是一個對象,右邊是一個函數。該操作解決的問題是:在f的原型鏈上,是否有fn.prototype對象?(通過bind強綁生成的函數沒有prototype屬性)

  如果要直接判斷兩個對象是否存在原型關系,可以用以下幾個方法:

    function fn() {}var f = new fn;//是否是原型關系console.log(fn.prototype.isPrototypeOf(f)); //true//展示原型console.log(Object.getPrototypeOf(f)); //Object{}//瀏覽器私有實現console.log(f.__proto__); //Object{}

  絕大多數瀏覽器支持__proto__方法來訪問[[prototype]]屬性。(__開頭的屬性表明這不是ECMA標準,還有很多其他的屬性也以__開頭)

  現在ES6可以用Object.getPrototypeOf()與Object.setPropertyOf()來獲取和設置原型,相當于原生支持了__proto__。

  

  Object.create()會創建一個對象,并關聯到參數對象中,避免了new操作符與生成對應的constructor,prototype。

  如果舊瀏覽器不支持,可以用下面的代碼模擬:

    if (!Object.create) {Object.create = function(o) {function f() {};f.prototype = o;return new f();}}

  關于new操作符和原型,如果下面的代碼可以理解,那就沒問題了~

    function fn(a) {this.a = a;}fn.prototype = {};Object.defineProperty(fn.prototype, 'a', {value: 1,configurable: true,enumerable: true,writable: false});//嚴格模式new會報錯var f = new fn(3);console.log(f); //無效!console.log(f.a); //1

  完結撒花!

?

轉載于:https://www.cnblogs.com/QH-Jimmy/p/6477143.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/372840.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/372840.shtml
英文地址,請注明出處:http://en.pswp.cn/news/372840.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

JUnit和Hamcrest:在assertEquals上進行改進

在我的博客文章中&#xff0c;Java越來越接受靜態導入嗎&#xff1f; &#xff0c;我討論了在Java中越來越多地使用靜態導入來使代碼在某些情況下更流暢。 Java 單元測試特別受靜態導入的影響&#xff0c;在此博客文章中&#xff0c;我提供了一個簡單的示例&#xff0c;說明如何…

mysql delete temporary denied_這些錯誤是什么意思?djang中的mysql

我試著運行一個程序&#xff0c;我被給予了一個例子&#xff0c;它就像一個購物網站&#xff0c;使用MySQL數據庫而不是Django提供的原始數據庫&#xff01;我只是想看看有沒有人理解這些錯誤的含義&#xff1f;任何信息都將不勝感激&#xff01;我本可以提供網頁的代碼&#x…

C語言 · 芯片測試

基礎練習 芯片測試 時間限制&#xff1a;1.0s 內存限制&#xff1a;512.0MB問題描述有n&#xff08;2≤n≤20&#xff09;塊芯片&#xff0c;有好有壞&#xff0c;已知好芯片比壞芯片多。每個芯片都能用來測試其他芯片。用好芯片測試其他芯片時&#xff0c;能正確給出被測試…

Animation用法

測試代碼及說明&#xff1a; <!DOCTYPE html> <html lang"en-US"> <head><meta charset"UTF-8"><title>Simple CSS3 Animation</title><style type"text/css">#demo {position: absolute;left: 30%;t…

mysql dese_MySQL 5.6-類似于DENSE_RANK的功能,無需訂購

小編典典對于 MySQL版本<8.0(OP的版本是5.6)&#xff1a;問題陳述看起來需要DENSE_RANK功能groupVarian; 但是事實并非如此。正如 GordonLinoff解釋的那樣 &#xff1a;您似乎希望按它們在數據中出現的順序來枚舉它們。假設您的表名是t(請為您的代碼相應地更改表名和字段名)…

Spring和JSF集成:動態導航

通常&#xff0c;您的JSF應用程序將需要超越基本的靜態導航并開始做出動態導航決策。 例如&#xff0c;您可能想根據用戶的年齡重定向他們。 大多數JSF教程建議通過將命令的action屬性綁定到支持bean來實現動態導航&#xff1a; <h:commandButton action"#{bean.action…

通過富文本改變UITextFieldPlaceholder顏色

1、通過屬性 a、 //文字屬性(一般) NSMutableDictionary *attrs [NSMutableDictionary dictionary]; attrs[NSForegroundColorAttributeName] [UIColor blueColor]; NSAttributedString *placeholderStr [[NSAttributedString alloc] initWithString:"手機號" a…

阻塞/非阻塞/同步/異步方法和多線程的關系?沒有任何關系,倆不挨著

1.阻塞非阻塞異步同步是針對方法說的&#xff0c;是評判一個方法運行狀態的。和多線程完全兩個級別。 2.阻塞非阻塞異步同步是針對方法說的&#xff0c;是評判一個方法運行狀態的。和多線程完全兩個級別。 3.阻塞非阻塞異步同步是針對方法說的&#xff0c;是評判一個方法運行狀…

mysql備份 where_MySQL備份與還原

1.mysqldumpmysqlbinlog介紹mysqldump備份結合binlog日志恢復。MySQL備份一般采取全庫備份加日志備份的方式&#xff0c;例如每天執行一次全備份&#xff0c;每小時執行一次二進制日志備份&#xff0c;這樣在MySQL故障后可以使用全備份和日志備份將數據恢復到最后一個二進制日志…

JMeter:負載測試關系數據庫

Apache JMeter是完全使用Java編寫的性能測試工具。 可以在請求/響應模型上運行的任何應用程序都可以使用JMeter進行負載測試。 關系數據庫也不例外&#xff1a;接收sql查詢&#xff0c;執行它們并返回執行結果。 我將向您展示使用JMeter的圖形用戶界面設置測試方案有多么容易。…

new: Set up a window

Nehe的教程確實太老了&#xff0c;不過我認為它也能夠讓我了解OpenGL3.2以前的管線渲染模式&#xff0c;即使它在現在已經不常見了。因為想要了解&#xff0c;所以我還是會看完Nehe的教程。 現在這是一個新的教程 - JoeyDeVries的教程&#xff0c;可以說是網上最好的OpenGL教程…

Python全棧開發:socket

Socket socket通常也稱作"套接字"&#xff0c;用于描述IP地址和端口&#xff0c;是一個通信鏈的句柄&#xff0c;應用程序通常通過"套接字"向網絡發出請求或者應答網絡請求。 socket起源于Unix&#xff0c;而Unix/Linux基本哲學之一就是“一切皆文件”&…

oracle sga pga mysql_修改Oracle數據庫SGA和PGA大小

SGA的大小&#xff1a;一般物理內存20%用作操作系統保留&#xff0c;其他80%用于數據庫。SGA普通數據庫可以分配40%-60%之間&#xff0c;PGA可以分配20%-40%之間。1、以dba身份登錄并查看SGA信息&#xff1a;SQL>show parameter sga&#xff1b;查看PGA信息&#xff1a;SQL&…

NetBeans 7.1:創建自定義提示

我已經在帖子中介紹了一些我最喜歡的NetBeans提示 &#xff0c;這些信息是用于使Java代碼現代化的七個NetBeans提示和七個不可或缺的NetBeans Java提示 。 這兩個帖子中涉及的十四個提示僅占NetBeans支持的“即開即用”提示總數的一小部分。 但是&#xff0c;由于NetBeans 7.1使…

今年暑假不AC

Problem Description “今年暑假不AC&#xff1f;”“是的。”“那你干什么呢&#xff1f;”“看世界杯呀&#xff0c;笨蛋&#xff01;”“#$%^&*%...”確實如此&#xff0c;世界杯來了&#xff0c;球迷的節日也來了&#xff0c;估計很多ACMer也會拋開電腦&#xff0c;奔向…

qregexp括號匹配_轉:Qt的正則表達式和QRegExp

考慮一下我們經常遇到的問題&#xff0c;比如gemfield想從青島之光讀書(www.civilnet.cn/book)中找一個關鍵的電話號碼&#xff0c;通常第一步就是將書中所有的電話號碼查找出來放在手邊。那么怎么擬定查詢條件呢&#xff1f;電話的格式有如下幾種&#xff1a;01088888888010 8…

具有Tron效果的JavaFX 2 Form

這是一個具有TRON效果的簡單JavaFX登錄表單。 在此示例中&#xff0c;我使用CSS設置TextField和Button的樣式。 這是CSS和Effect代碼的片段&#xff1a; .text-field{-fx-background-color: transparent;-fx-border-color: #00CCFF;-fx-text-fill: white; }.password-field{-fx…

Spring注解Annotion詳解

概述 注釋配置相對于 XML 配置具有很多的優勢&#xff1a; 它可以充分利用 Java 的反射機制獲取類結構信息&#xff0c;這些信息可以有效減少配置的工作。如使用 JPA 注釋配置 ORM 映射時&#xff0c;我們就不需要指定 PO 的屬性名、類型等信息&#xff0c;如果關系表字段和 PO…

CopyOnWrite容器

1.簡介 1.CopyOnWrite是程序優化的策略,當共享的內容需要修改時,復制出去一份進行修改,然后將原來的引用指向修改完的 2.java并發包(java.util.concurrent)中CopyOnWriteArrayList和CopyOnWriteArraySet實現了這個并發容器 3.好處:因為寫時是在復制的一份上操作,所以可以并發的…

Akka的字數統計MapReduce

在我與Akka的日常工作中&#xff0c;我最近寫了一個字數映射表簡化示例。 本示例實現了Map Reduce模型&#xff0c;該模型非常適合橫向擴展設計方法。 流 客戶端系統&#xff08;FileReadActor&#xff09;讀取文本文件&#xff0c;并將每一行文本作為消息發送給ClientActor。…