深入理解javascript函數系列第三篇

來源:互聯網
上載者:User

標籤:包含   回調   ict   最大   參考   屬性工作表   全域對象   rom   return   

前面的話

  函數是javascript中特殊的對象,可以擁有屬性和方法,就像普通的對象擁有屬性和方法一樣。甚至可以用Function()建構函式來建立新的函數對象。本文是深入理解javascript函數系列第三篇——屬性和方法

 

屬性

【length屬性】

  函數系列第二篇中介紹過,arguments對象的length屬性工作表示實參個數,而函數的length屬性則表示形參個數

function add(x,y){    console.log(arguments.length)//3    console.log(add.length);//2}add(1,2,3);

【name屬性】

  函數定義了一個非標準的name屬性,通過這個屬性可以訪問到給定函數指定的名字,這個屬性的值永遠等於跟在function關鍵字後面的標識符,匿名函數的name屬性為空白

//IE11-瀏覽器無效,均輸出undefined//chrome在處理匿名函數的name屬性時有問題,會顯示函數運算式的名字function fn(){};console.log(fn.name);//‘fn‘var fn = function(){};console.log(fn.name);//‘‘,在chrome瀏覽器中會顯示‘fn‘var fn = function abc(){};console.log(fn.name);//‘abc‘    

  [注意]name屬性早就被瀏覽器廣泛支援,但是直到ES6才將其寫入了標準

  ES6對這個屬性的行為做出了一些修改。如果將一個匿名函數賦值給一個變數,ES5的name屬性,會返回Null 字元串,而ES6的name屬性會返回實際的函數名

var func1 = function () {};func1.name //ES5:  ""func1.name //ES6: "func1"

  如果將一個具名函數賦值給一個變數,則ES5和ES6的name屬性都返回這個具名函數原本的名字

var bar = function baz() {};bar.name //ES5: "baz"bar.name //ES6: "baz"

  Function建構函式返回的函數執行個體,name屬性的值為“anonymous”

(new Function).name // "anonymous"

  bind返回的函數,name屬性值會加上“bound ”首碼

function foo() {};foo.bind({}).name // "bound foo"(function(){}).bind({}).name // "bound "

【prototype屬性】

  每一個函數都有一個prototype屬性,這個屬性指向一個對象的引用,這個對象稱做原型對象(prototype object)。每一個函數都包含不同的原型對象。將函數用做建構函式時,新建立的對象會從原型對象上繼承屬性

function fn(){};var obj = new fn;fn.prototype.a = 1;console.log(obj.a);//1

 

方法

【apply()和call()】

  每個函數都包含兩個非繼承而來的方法:apply()和call()。這兩個方法的用途都是在特定的範圍中調用函數,實際上等於函數體內this對象的值

  要想以對象o的方法來調用函數f(),可以這樣使用call()和apply()

f.call(o);f.apply(o);

  假設o中不存在m方法,則等價於:

o.m = f; //將f儲存為o的臨時方法o.m(); //調用它,不傳入參數delete o.m; //將臨時方法刪除

  下面是一個實際的例子

window.color = "red";var o = {color: "blue"};function sayColor(){    console.log(this.color);}sayColor();            //redsayColor.call(this);   //redsayColor.call(window); //redsayColor.call(o);      //blue
//sayColor.call(o)等價於:o.sayColor = sayColor;o.sayColor();   //bluedelete o.sayColor;

  apply()方法接收兩個參數:一個是在其中運行函數的範圍(或者可以說成是要調用函數的母對象,它是調用上下文,在函數體內通過this來獲得對它的引用),另一個是參數數組。其中,第二個參數可以是Array的執行個體,也可以是arguments對象

function sum(num1, num2){    return num1 + num2;}//因為運行函數的範圍是全域範圍,所以this代表的是window對象function callSum1(num1, num2){    return sum.apply(this, arguments);}function callSum2(num1, num2){    return sum.apply(this, [num1, num2]);}console.log(callSum1(10,10));//20console.log(callSum2(10,10));//20

  call()方法與apply()方法的作用相同,它們的區別僅僅在於接收參數的方式不同。對於call()方法而言,第一個參數是this值沒有變化,變化的是其餘參數都直接傳遞給函數。換句話說,在使用call()方法時,傳遞給函數的參數必須逐個列舉出來

function sum(num1, num2){    return num1 + num2;}function callSum(num1, num2){    return sum.call(this, num1, num2);}console.log(callSum(10,10));   //20

  至於是使用apply()還是call(),完全取決於採取哪種函數傳遞參數的方式最方便。如果打算直接傳入arguments對象,或者包含函數中先接收到的也是一個數組,那麼使用apply()肯定更方便;否則,選擇call()可能更合適

  在非strict 模式下,使用函數的call()或apply()方法時,null或undefined值會被轉換為全域對象。而在strict 模式下,函數的this值始終是指定的值

var color = ‘red‘;function displayColor(){    console.log(this.color);}displayColor.call(null);//red
var color = ‘red‘;function displayColor(){    ‘use strict‘;    console.log(this.color);}displayColor.call(null);//TypeError: Cannot read property ‘color‘ of null

應用 

【1】調用對象的原生方法

var obj = {};obj.hasOwnProperty(‘toString‘);// falseobj.hasOwnProperty = function (){  return true;};obj.hasOwnProperty(‘toString‘);// trueObject.prototype.hasOwnProperty.call(obj, ‘toString‘);// false

【2】找出數組最大元素

  javascript不提供找出數組最大元素的函數。結合使用apply方法和Math.max方法,就可以返回數組的最大元素

var a = [10, 2, 4, 15, 9];Math.max.apply(null, a);//15

【3】將類數組對象轉換成真正的數組

Array.prototype.slice.apply({0:1,length:1});//[1]

  或者

[].prototype.slice.apply({0:1,length:1});//[1]

【4】綁定回呼函數的對象

  由於apply方法(或者call方法)不僅綁定函數執行時所在的對象,還會立即執行函數,因此不得不把綁定語句寫在一個函數體內。更簡潔的寫法是採用下面介紹的bind方法

var o = {};o.f = function () {  console.log(this === o);}var f = function (){  o.f.apply(o);};$(‘#button‘).on(‘click‘, f);

【bind()】

  bind()是ES5新增的方法,這個方法的主要作用就是將函數綁定到某個對象 

  當在函數f()上調用bind()方法並傳入一個對象o作為參數,這個方法將返回一個新的函數。以函數調用的方式調用新的函數將會把原始的函數f()當做o的方法來調用,傳入新函數的任何實參都將傳入原始函數

  [注意]IE8-瀏覽器不支援

function f(y){    return this.x + y; //這個是待綁定的函數}var o = {x:1};//將要綁定的對象var g = f.bind(o); //通過調用g(x)來調用o.f(x)g(2);//3

相容代碼

function bind(f,o){    if(f.bind){        return f.bind(o);    }else{        return function(){            return f.apply(o,arguments);        }    }}    

  bind()方法不僅是將函數綁定到一個對象,它還附帶一些其他應用:除了第一個實參之外,傳入bind()的實參也會綁定到this,這個附帶的應用是一種常見的函數式編程技術,有時也被稱為‘柯裡化‘(currying)

var sum = function(x,y){    return x+y;}var succ = sum.bind(null,1);succ(2); //3,x綁定到1,並傳入2作為實參y
function f(y,z){    return this.x + y + z;}var g = f.bind({x:1},2);g(3); //6,this.x綁定到1,y綁定到2,z綁定到3

  使用bind()方法實現柯裡化可以對函數參數進行拆分

function getConfig(colors,size,otherOptions){    console.log(colors,size,otherOptions);}var defaultConfig = getConfig.bind(null,‘#c00‘,‘1024*768‘);defaultConfig(‘123‘);//‘#c00 1024*768 123‘defaultConfig(‘456‘);//‘#c00 1024*768 456‘

【toString()】

  函數的toString()執行個體方法返回函數代碼的字串,而靜態toString()方法返回一個類似‘[native code]‘的字串作為函數體

function test(){    alert(1);//test}test.toString();/*"function test(){                    alert(1);//test                  }"*/Function.toString();//"function Function() { [native code] }"

【toLocaleString()】

  函數的toLocaleString()方法和toString()方法返回的結果相同

function test(){    alert(1);//test}test.toLocaleString();/*"function test(){                    alert(1);//test                  }"*/Function.toLocaleString();//"function Function() { [native code] }"

【valueOf()】

  函數的valueOf()方法返回函數本身

function test(){    alert(1);//test}test.valueOf();/*function test(){                    alert(1);//test                  }*/typeof test.valueOf();//‘function‘Function.valueOf();//Function() { [native code] }

 

參考資料

【1】  W3School-Javascript進階教程——Function對象 http://www.w3school.com.cn/js/
【2】  阮一峰Javascript標準參考教程——函數的屬性和方法 http://javascript.ruanyifeng.com/grammar/
【3】《javascript權威指南(第6版)》第8章 函數
【4】《javascript進階程式設計(第3版)》第5章 參考型別
【5】《javascript DOM編程藝術(第2版)》第2章 javascript文法
【6】《javascript語句精粹》第4章 函數

深入理解javascript函數系列第三篇

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.