js函數的屬性和方法

js函數的屬性和方法

前面的話

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

 

屬性

【length屬性】html

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

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

【name屬性】chrome

  函數定義了一個非標準的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屬性,會返回空字符串,而ES6的name屬性會返回實際的函數名瀏覽器

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

  若是將一個具名函數賦值給一個變量,則ES5和ES6的name屬性都返回這個具名函數本來的名字app

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();            //red
sayColor.call(this);   //red
sayColor.call(window); //red
sayColor.call(o);      //blue
複製代碼
//sayColor.call(o)等價於:
o.sayColor = sayColor;
o.sayColor();   //blue
delete 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));//20
console.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()可能更合適

  在非嚴格模式下,使用函數的call()或apply()方法時,null或undefined值會被轉換爲全局對象。而在嚴格模式下,函數的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');// false
obj.hasOwnProperty = function (){
  return true;
};
obj.hasOwnProperty('toString');// true
Object.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】將一個數組的值push到另外一個數組中

var a = [];
Array.prototype.push.apply(a,[1,2,3]);
console.log(a);//[1,2,3]
Array.prototype.push.apply(a,[2,3,4]);
console.log(a);//[1,2,3,2,3,4]

  若是使用ES6中的不定參數則很是簡單

var a  = [...[1,2,3],...[2,3,4]];
console.log(a);//[1,2,3,2,3,4]

【5】綁定回調函數的對象

  因爲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.prototype.bind = function(context){
  var self = this;
  return function(){
    return self.apply(context,arguments);
  }
}
複製代碼

  一般,會把它實現得稍微複雜一點,使得能夠填入一些參數

複製代碼
Function.prototype.bind = function(context){
  var self = this,
      context = [].shift.call(arguments),
      args = [].slice.call(arguments);
  return function(){
    return self.apply(context,[].concat.call(args,[].slice.call(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函數系列第三篇——屬性和方法 - 小火柴的藍色理想 - 博客園https://www.cnblogs.com/xiaohuochai/p/5707378.html

相關文章
相關標籤/搜索