對js中Function的淺見 -开发者知识库

對js中Function的淺見 -开发者知识库,第1张

它到底是什么

String Array 都是系統內置對象(已經定義好,可以直接使用)當然,這貨也是一樣,我們之前定義的函數,其實就是一個這貨的實例。

JS中,所有的對象都是由函數實現的,函數的數據類型是objectSo,我們以前定義的函數也是一個對象。

 

幾種寫法

 1  function fn1(a,b){
2 return a b;
3 }
4
5 //前面表示參數,后面表示函數語句
6 var fn2 = new Function("a","b","return a b");
7
8 // 匿名函數
9 var fn3=function(a,b){
10 return a b;
11 }
12
13
14 console.log(fn1(1,2));
15 console.log(fn2(1,2));
16 console.log(fn3(1,2)); // 注意,一定要在聲明函數的后面調用

 

另外,如果函數沒有明確的返回值,或者調用了沒有參數的return,那么它真正返回的值是undefined

 1 function fn(){
2 //.....
3 }
4
5
6 function fn1(){
7 return;
8 }
9
10
11 console.log(fn()===undefined); // true
12 console.log(fn1()===undefined); // true

 

arguments  

arguments只有在代碼運行的時候才起作用,它是一個數組(准確的說是偽數組),保存函數的參數。

 1 function fn(){
2 var sum=0;
3 for(var i=0;i<arguments.length;i ){
4 sum =arguments[i];
5 }
6 return sum;
7 }
8
9 var sum = fn(1,2);
10 var sum2 = fn(1,2,3);
11 console.log(sum); // 3
12 console.log(sum2); // 6
13
14 function fn1(a,b,c,d){
15 console.log(arguments.length);
16 console.log(arguments[0]);
17 }
18
19 fn1(); // 0 、 undefined
20 fn1(1); // 1 、 1
21 fn1('a',2); // 2 、 a
22 fn1('李志',2,3); // 3 、 李志
23 fn1('李B',2,2,3,4,4); // 6 、 李B

 

Length

我們需要了解兩個東東,形參與實參(不同的資料書籍可能叫法有所差異)

形參:函數定義的時候的參數  實參:調用函數的時候傳遞的參數

length指的是形參個數   arguments.length指的是實參個數

1  function fn(a, b) {
2 console.log(fn.length);
3 console.log(arguments.length);
4 }
5
6 fn(1, 2); // 2 2
7 fn(1); // 2 1

 

call  apply

1,借用另一個對象的方法  2,替換this指向

Apply方法  調用函數,並用指定對象替換函數的this值,同時用指定數組替換函數的參數。

Call方法    調用一個對象的方法,用另一個對象替換當前對象。

 1     //對象1
2 var obj1={
3 getAllStudentsNumbers:function(sum,sum1){
4 return sum sum1}
5 };
6
7 //對象2
8 var obj2={
9 getDetail:function(){
10 return {name:'阿拉三',age:'18'}
11 }
12 };
13 console.log(obj1.getAllStudentsNumbers.call(obj2,10,200)); // 210
14 console.log(obj1.getAllStudentsNumbers.apply(obj2,[10,200])); // 210

Function.apply(obj,args)方法能接收兩個參數
obj:這個對象將代替Function類里this對象
args:這個是數組,它將作為參數傳給Functionargs-->arguments

 

我們通過如下方式將其轉換成數組

1 /* slice : 截取數組,返回的還是數組,這里我們截取全部  */
2 var divs = document.getElementsByTagName("div")
3 var domNodes = Array.prototype.slice.call(divs);

還可以實現繼承,在上篇文章中說過,這里不做贅述。

 

caller callee

caller屬性 獲取調用當前函數的函數。caller屬性只有當函數正在執行時才被定義。

返回函數調用者,主要用於察看函數本身被哪個函數調用.

 1     function fn() {
2 //判斷某函數是否被調用
3 if (fn.caller) {
4 alert(fn.caller.toString());
5 } else {
6 alert("函數直接執行");
7 }
8 }
9
10 function fn1() {
11 fn();
12 }
13 fn1();
14 fn();

 

callee屬性 返回正被執行的 Function 對象,即指定的Function 對象的正文。

如下是一個遞歸算法 計算 1 2 3 4 ... n

什么是遞歸?    可以這樣理解,一個方法,自己調用自己,用上一次調用得出的結果作為這次的參數。

傳統方式的缺點:

1、破壞了,零重復法則,當一旦函數名稱更改,需要更改多處

2、fn是一個全局變量,fn內部一般使用局部變量,而這里是一個全局變量,這是一個潛在的全局變量污染

1 var fn=function(n){
2 return n>0 ? n fn(n-1) : 0;
3 }
4 console.log('采用傳統方式:' fn(10));

優點:這樣就讓代碼更加簡練。又防止了全局變量的污染

1 var fn=(function(n){
2 return n>0 ? n arguments.callee(n-1) : 0;
3 })(10);
4 console.log('采用callee方式: ' fn);

 

constructor prototype

constructor屬性,就是用來構造對象實例的函數引用。

prototype屬性,獲取對象的原型。

每一個構造函數都有一個prototype屬性,指向另一個對象。這個對象的所有屬性和方法,都會被構造函數的實例繼承。這意味着,我們可以把那些不變的屬性和方法,直接定義在prototype對象上。

 contructorprototype屬性是系統自動生成的。但本質上只是是函數對象的屬性而已。

對象是一個函數,而函數對象含有contructorprototype等屬性,

那么實例化的過程就是拷貝構造函數屬性的過程,所以每個實例自然就擁有了contructorprototype這兩個屬性。

 

自定義對象:函數實現的--函數又是Function的一個實例,所以這個自定義對象含有Function對象的一切屬性和方法

1 var product = function(){}
2 /*自動有一個 prototype屬性 它是一個對象--- 原型對象*/
3 /* product.prototype也是對象,對象都是函數實現的,這貨也包含Function對象的一切屬性和方法,所以他也有。*/
4 product.prototype.buy=function(){}
5 product.prototype={}

 

bind  

Bind方法,創建具有與原始函數相同的主體的綁定函數。 在綁定功能中,this對象解析為傳入的對象。 該綁定函數具有指定的初始參數。

為了能在改變了上下文之后繼續引用到this,大家通常選擇使用self that _this 等方式先保存起來。這是完全可以的,現在有了bind:

 

 1 var obj={
2 fn1:function(){
3 console.log(1);
4 },
5 fn2:function(){
6 console.log(2);
7 },
8 fn3:function(fn){
9 fn();
10 console.log(3);
11 },
12 fn4:function(){
13 // var that=this; // 還保存嗎?
14 // this.fn3(function(){
15 // console.log(4);
16 // that.fn1();
17 // that.fn2();
18 // });
19 this.fn3(function(){
20 console.log(4);
21 this.fn1();
22 this.fn2();
23 }.bind(this)); // 咦,發生什么?
24 },
25 }
26 obj.fn4();

再看一眼:

1  var foo={
2 x:3,
3 }
4 var bar=function(){
5 console.log(this.x);
6 }
7 bar();
8 var boundFunc=bar.bind(foo);
9 boundFunc();

想到了什么?call? apply? 沒錯,看下面三者的區別:

1 fn1.hello.call(fn2,1,2,3);
2 fn1.hello.apply(fn2,[1,2,3]);
3 fn1.hello.bind(fn2)(1,2,3);

好消息是,IE8以下並不支持。腫么辦?  

沒關系,大牛們寫好了,我們來看一下

 1 if (!Function.prototype.bind) {
2 Function.prototype.bind = function (oThis) {
3 if (typeof this !== "function") {
4 throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
5 }
6 var aArgs = Array.prototype.slice.call(arguments, 1),
7 fToBind = this,
8 fNOP = function () {},
9 fBound = function () {
10 return fToBind.apply(this instanceof fNOP ? this : oThis || this ,
11 aArgs.concat(Array.prototype.slice.call(arguments)));
12 };
13 fNOP.prototype = this.prototype;
14 fBound.prototype = new fNOP();
15 return fBound;
16
17 };
18 }

 

最后:

JS中,函數的使用是非常之靈活,比如閉包、立即函數、等等等等,以后有機會專門討論。

 

最佳答案:

本文经用户投稿或网站收集转载,如有侵权请联系本站。

发表评论

0条回复