摘要:另外注意,構造函數的函數名第一個字母大寫規則約定。綁定函數被調用時,也接受預設的參數提供給原函數。一個綁定函數也能使用操作符創建對象這種行為就像把原函數當成構造器。
前言
本來this應該放在《上下文環境和作用域》中來講,結果發現自己整理的時候,例子越來越多,所以多帶帶寫一篇用于加深理解,以后工作或項目中發現一些this相關問題可以進一步完善文章的例子。
this 概念在函數中this到底取何值,是在函數真正被調用執行的時候確定的,函數定義的時候確定不了
因為this的取值是執行上下文環境的一部分,每次調用函數,都會產生一個新的執行上下文環境。
構造函數所謂構造函數就是用來new對象的函數。其實嚴格來說,所有的函數都可以new一個對象,但是有些函數的定義是為了new一個對象,而有些函數則不是。另外注意,構造函數的函數名第一個字母大寫(規則約定)。例如:Object、Array、Function等。
function Foo() { this.name = "yzh"; this.year = 1996; console.log(this); //Object { name: "yzh", year: 1998 } } var f1 = new Foo(); console.log(f1.name); //yzh console.log(f1.year); //1996
以上代碼中,如果函數作為構造函數用,那么其中的this就代表它即將new出來的對象。
注意,以上僅限newFoo()的情況,即Foo函數作為構造函數的情況。如果直接調用Foo函數,而不是new Foo(),情況就大不一樣了。
function Foo() { this.name = "yzh"; this.year = 1996; console.log(this); //Object { name: "yzh", year: 1998 } } Foo(); //window
這種情況下this是window。
函數作為對象的一個屬性如果函數作為對象的一個屬性時,并且作為對象的一個屬性被調用時,函數中的this指向該對象。
var obj = { x: 10, fn: function() { console.log(this); //Object { x: 10, fn: fn() } console.log(this.x); //10 } }; obj.fn();
以上代碼中,fn不僅作為一個對象的一個屬性,而且的確是作為對象的一個屬性被調用。結果this就是obj對象。
如果fn函數不作為obj的一個屬性被調用,會是什么結果呢?
var obj = { x: 10, fn: function() { console.log(this); //window console.log(this.x); //undefined } }; var f1 = obj.fn; f1();
如上代碼,如果fn函數被賦值到了另一個變量中,并沒有作為obj的一個屬性被調用,那么this的值就是window,this.x為undefined。
函數用call或者apply調用為了防止看不懂這塊先理解下基礎并重要的東西
函數內部屬性在函數內部,有兩個特殊的對象:arguments和this.
主要介紹下arguments,它是類數組對象,包含傳入函數的所有參數,這個對象還有一個叫callee的屬性,該屬性為一個指針,指向擁有這個arguments對象的函數。
這個例子主要用于消除函數的執行與同名函數的緊密耦合現象。代碼如下:
function factorial(num) { if (num <= 1) { return 1; } else { // return num * factorial(num - 1); //1.一般的遞歸算法運用 return num * arguments.callee(num - 1) //2.更好的做法 } } var trueFactorial = factorial; factorial = function() { return 0; }; alert(trueFactorial(5)); //120 alert(factorial(5)); //0函數屬性
每個函數都包含兩個屬性:length和prototype.
length表示函數希望接受的命名參數的個數
function sayName(name){ alert(name); } function sum(num1, num2){ return num1 + num2; } function sayHi(){ alert("hi"); } alert(sayName.length); //1 alert(sum.length); //2 alert(sayHi.length); //0
prototype屬性這里不再重復介紹。
函數方法每個函數都包含兩個非繼承而來的方法:apply()和call(),這兩個方法的用途都是在特定的作用域中調用函數,實際上等于設置函數體內的this對象值。
apply()方法接受兩個參數:一個是在其中運行函數的作用域,另一個是參數數組。
function sum(num1, num2){ return num1 + num2; } function callSum1(num1, num2){ return sum.apply(this, arguments); } function callSum2(num1, num2){ return sum.apply(this, [num1, num2]); } alert(callSum1(10,10)); //20 alert(callSum2(10,10)); //20
callsSum1()執行sum()函數時傳入this作為this值(在全局作用域中調用,所以傳入的對象為window對象)下面的例子同理。
call()方法與apply()方法差不多,區別在于接受參數的方式不同。簡單來說就是:傳遞給函數的參數必須逐個列舉出來。(如果是無參函數就不用傳參數)
function sum(num1, num2){ return num1 + num2; } function callSum(num1, num2){ return sum.call(this, num1, num2); } alert(callSum(10,10)); //20
傳遞參數并非兩個函數的真正用武之地,真正強大的地方是擴充函數賴以運行的作用域
window.color = "red"; var o = { color: "blue" }; function sayColor(){ alert(this.color); } sayColor(); //red sayColor.call(this); //red sayColor.call(window); //red sayColor.call(o); //blue
如下代碼如果不用函數的方法來實現。
window.color = "red"; var o = { color: "blue" }; function sayColor(){ alert(this.color); } sayColor(); //red o.sayColor = sayColor; o.sayColor(); //blue
如果要輸出o對象里的color屬性值,必須把sayColor函數賦給對象o并調用 o.sayColor()時,this引用的對象為o
回歸要講的例子當一個函數被call和apply調用時,this的值就取傳入的對象的值。
var obj = { x: 10 }; var fn = function() { console.log(this); //Object { x: 10 } console.log(this.x); //10 }; fn.call(obj);全局 & 調用普通函數
在全局環境下,this永遠是window,這個應該沒有非議。
console.log(this === window); //true
普通函數在調用時,其中的this也都是window。
var x = 10; var fn = function() { console.log(this); //window console.log(this.x); //10 } fn();
注意以下的情況
var obj = { x: 10, fn: function() { function f() { console.log(this); //Window console.log(this.x); //undefined } f(); } }; obj.fn();
函數f雖然是在obj.fn內部定義的,但是它仍然是一個普通的函數,this仍然指向window。
構造函數的prototype中,this代表著什么總結:this指向調用該函數的對象
function Fn() { this.name = "yzh"; this.year = 1996; } Fn.prototype.getName = function() { console.log(this.name); } var f1 = new Fn(); f1.getName(); //yzh
在Fn.prototype.getName函數中,this指向的是f1對象。因此可以通過this.name獲取f1.name的值
bind()bind()方法創建一個新的函數, 當被調用時,它的this關鍵字被設置為提供的值 ,在調用新函數時,提供任何一個給定的參數序列。
這個函數其實也很重要,只是當時紅寶書也沒提及很多。
語法參數fun.bind(thisArg[, arg1[, arg2[, ...]]])
返回值thisArg
當綁定函數被調用時,該參數會作為原函數運行時的 this 指向。當使用new 操作符調用綁定函數時,該參數無效。arg1, arg2, ...
當綁定函數被調用時,這些參數將置于實參之前傳遞給被綁定的方法。
描述返回由指定的this值和初始化參數改造的原函數拷貝
bind() 函數會創建一個新函數(稱為綁定函數),新函數與被調函數(綁定函數的目標函數)具有相同的函數體(在 ECMAScript 5 規范中內置的call屬性)。當目標函數被調用時 this 值綁定到 bind() 的第一個參數,該參數不能被重寫。綁定函數被調用時,bind() 也接受預設的參數提供給原函數。一個綁定函數也能使用new操作符創建對象:這種行為就像把原函數當成構造器。提供的 this 值被忽略,同時調用時的參數被提供給模擬函數。
示例創建綁定函數
this.x = 9; var module = { x: 81, getX: function() { return this.x; } }; module.getX(); // 返回 81 var retrieveX = module.getX; retrieveX(); // 返回 9, 在這種情況下,"this"指向全局作用域 // 創建一個新函數,將"this"綁定到module對象 // 新手可能會被全局的x變量和module里的屬性x所迷惑 var boundGetX = retrieveX.bind(module); boundGetX(); // 返回 81End
歡迎拍磚,有更多的好的例子,歡迎提出,文中有誤的地方也歡迎指正。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/83091.html
摘要:繼承和前面兩篇文章中的知識非常相關,如果對函數創建原理和原型鏈不熟悉,請猛戳高級程序設計筆記創建對象高級程序設計筆記原型圖解繼承,通俗的說,就是將自身不存在的屬性或方法,通過某種方式為自己所用文章分別介紹原型鏈繼承繼承借用構造函數繼承組合繼 繼承和前面兩篇文章中的知識非常相關,如果對函數創建原理和原型鏈不熟悉,請猛戳:《javascript高級程序設計》筆記:創建對象《javascri...
摘要:上一篇你不知道的筆記寫在前面這是年第一篇博客,回顧去年年初列的學習清單,發現僅有部分完成了。當然,這并不影響年是向上的一年在新的城市穩定連續堅持健身三個月早睡早起游戲時間大大縮減,學會生活。 上一篇:《你不知道的javascript》筆記_this 寫在前面 這是2019年第一篇博客,回顧去年年初列的學習清單,發現僅有部分完成了。當然,這并不影響2018年是向上的一年:在新的城市穩定、...
摘要:如果直接調用構造函數,那么會指向全局對象然后你的代碼就會覆蓋的原生。凍結對象最嚴格的防篡改就是凍結對象。中央定時器動畫地址參考書籍高級程序設計忍者秘籍 1 安全類型檢測 javascript內置類型檢測并不可靠 safari某些版本( var person = {name: wdd}; undefined > Object.preventExtensions(person); Obj...
摘要:特性這樣指定事件處理程序具有一些獨到之處。級事件處理程序通過獲得要操作對象的引用,用把一個函數賦值給一個事件處理程序屬性,比如。以這種方式添加的事件處理程序會在事件流的冒泡階段被捕獲。級事件處理程序級事件定義了兩個方法,。 一、事件處理程序 響應某個事件的函數叫做事件處理程序(或事件偵聽器),為事件指定處理程序的方式有下面幾種。 1、html特性 這樣指定事件處理程序具有一些獨到之處...
閱讀 2416·2021-11-25 09:43
閱讀 1195·2021-09-07 10:16
閱讀 2603·2021-08-20 09:38
閱讀 2937·2019-08-30 15:55
閱讀 1449·2019-08-30 13:21
閱讀 884·2019-08-29 15:37
閱讀 1435·2019-08-27 10:56
閱讀 2093·2019-08-26 13:45