[TOC]
****
## 1 函數聲明與表達式
## 2 函數的調用
###1 f()
直接調用函數
###2 f.call(obj,a1,a2..)
obj作為函數體內this的指向對象
a1,a2,..等作為函數的參數
call()方法使用一個指定的this值和若干個指定的參數調用函數或方法。
調用一個函數,可以使用不同的this對象。即call方法的第一個參數
通過call方法,可以在一個對象上調用另一個對象的方法。
`fun.call(thisArg[,arg1[,arg2[,....]]])`
> thisArg
1 為空,或者null,undefined,函數中的this指向window對象
2 值為數字字符串布爾值會自動包裝為對象
3 傳遞另一個函數名,this指向函數的引用。
4 傳遞一個對象 則指向這個對象
> arg1,arg2....
參數列表
例子1
~~~
function a(){
//輸出函數a中的this對象
console.log(this);
}
//定義函數b
function b(){}
//定義對象obj
var obj = {name:'test'};
a.call(); //window
a.call(null); //window
a.call(undefined);//window
a.call(1); //Number
a.call(''); //String
a.call(true); //Boolean
a.call(b);// function b(){}
a.call(obj); //Object
~~~
例子2
~~~
function greet() {
var reply = [this.person, '是一個輕量的', this.role].join(' ');
console.log(reply);
}
var i = {
person: 'JSLite.io', role: 'Javascript 庫。'
};
greet.call(i);
// JSLite.io 是一個輕量的 Javascript 庫。
~~~
例子3
~~~
var animals = [
{species: 'Lion', name: 'King'},
{species: 'Whale', name: 'Fail'}
];
for (var i = 0; i < animals.length; i++) {
(function (i) {
this.print = function () {
console.log('#' + i + ' ' + this.species + ': ' + this.name);
}
this.print();
}).call(animals[i], i);
}
//#0 Lion: King
//#1 Whale: Fail
~~~
例子4
~~~
var a = {
name:'JSLite.io', //定義a的屬性
say:function(){ //定義a的方法
console.log("Hi,I'm function a!");
}
};
function b(name){
console.log("Post params: "+ name);
console.log("I'm "+ this.name);
this.say();
}
b.call(a,'test');
//Post params: test
//I'm onepixel
//I'm function a!
~~~
###3 f.apply(obj,[])
obj作為函數體內this的指向對象
[]作為函數的參數數組。
與call基本相同,區別在于參數列表以數組形式表示。
`fun.apply(thisArg[,argsArrat])`
例子1
~~~~
function jsy(x,y,z){
console.log(x,y,z);
}
jsy.apply(null,[1,2,3]);
// 1 2 3
~~~~
例子2
~~~~
Function.prototype.construct = function(aArgs) {
var fConstructor = this,
fNewConstr = function() {
fConstructor.apply(this, aArgs);
};
fNewConstr.prototype = fConstructor.prototype;
return new fNewConstr();
};
function MyConstructor () {
for (var nProp = 0; nProp < arguments.length; nProp++) {
console.log(arguments,this)
this["property" + nProp] = arguments[nProp];
}
}
var myArray = [4, "Hello world!", false];
var myInstance = MyConstructor.construct(myArray);
console.log(myInstance.property1); // logs "Hello world!"
console.log(myInstance instanceof MyConstructor); // logs "true"
console.log(myInstance.constructor); // logs "MyConstructor"
~~~
## 3 函數的屬性
## 4 函數的方法
## 5 閉包的使用
## 6 函數的創建
###1 bind()
bind()函數會創建一個新函數
> 1 es5新增的一個方法
2 傳參和call或者apply類似
3 不會執行對應的函數,call或apply則自動執行對應的函數
4 返回對函數的引用
`fun.bind(thisArg[,arg1[,arg2[,....]]])`
例子1
~~~
var obj = {name:'JSLite.io'};
/**
* 給document添加click事件監聽,并綁定EventClick函數
* 通過bind方法設置EventClick的this為obj,并傳遞參數p1,p2
*/
document.addEventListener('click',
EventClick.bind(obj,'p1','p2'),false);
//當點擊網頁時觸發并執行
function EventClick(a,b){
console.log(
this.name, //JSLite.io
a, //p1
b //p2
)
}
// JSLite.io p1 p2
~~~
兼容實現
~~~
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
// closest thing possible to the ECMAScript 5
// internal IsCallable function
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this, // this在這里指向的是目標函數
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP
? this //此時的this就是new出的obj
: oThis || this,//如果傳遞的oThis無效,就將fBound的調用者作為this
//將通過bind傳遞的參數和調用時傳遞的參數進行合并,并作為最終的參數傳遞
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
//將目標函數的原型對象拷貝到新函數中,因為目標函數有可能被當作構造函數使用
fBound.prototype = new fNOP();
//返回fBond的引用,由外部按需調用
return fBound;
};
}
~~~
應用例子 繼承
~~~
function Animal(name,weight){
this.name = name;
this.weight = weight;
}
function Cat(){
// 在call中將this作為thisArgs參數傳遞
// Animal方法中的this就指向了Cat中的this
// 所以Animal中的this指向的就是cat對象
// 在Animal中定義了name和weight屬性,就相當于在cat中定義了這些屬性
// cat對象便擁有了Animal中定義的屬性,從而達到了繼承的目的
Animal.call(this,'cat','50');
//Animal.apply(this,['cat','50']);
this.say = function(){
console.log("I am " + this.name+",my weight is " + this.weight);
}
}
//當通過new運算符產生了cat時,Cat中的this就指向了cat對象
var cat = new Cat();
cat.say();
//輸出=> I am cat,my weight is 50
~~~
原型擴展
~~~
function test(){
// 檢測arguments是否為Array的實例
console.log(
arguments instanceof Array, //false
Array.isArray(arguments) //false
);
// 判斷arguments是否有forEach方法
console.log(arguments.forEach);
// undefined
// 將數組中的forEach應用到arguments上
Array.prototype.forEach.call(arguments,function(item){
console.log(item); // 1 2 3 4
});
}
test(1,2,3,4);
~~~
## 6 參考鏈接
[重讀javascript的Function](https://segmentfault.com/a/1190000004252024)
[回味js基礎,call apply bind](https://segmentfault.com/a/1190000004568767)
- 概述
- 框架結構
- 編譯入口(\entries)
- web-compiler.js(web編譯)
- web-runtime.js(web運行時)
- web-runtime-wih-compiler.js(web編譯運行)
- web-server-renderer.js(web服務器渲染)
- 核心實現 (\core)
- index.js(核心入口)
- config.js(核心配置)
- core\util(核心工具)
- core\observer(雙向綁定)
- core\vdom(虛擬DOM)
- core\global-api(核心api)
- core\instance(核心實例)
- 模板編譯(\compiler)
- compiler\parser(模板解析)
- events.js(事件解析)
- helper.js(解析助手)
- directives\ref.js(ref指令)
- optimizer.js(解析優化)
- codegen.js(渲染生成)
- index.js(模板編譯入口)
- web渲染(\platforms\web)
- compiler(web編譯目錄)
- runtime(web運行時目錄)
- server(web服務器目錄)
- util(web工具目錄)
- 服務器渲染(\server)
- render-stream.js(流式渲染)
- render.js(服務器渲染函數)
- create-renderer.js(創建渲染接口)
- 框架流程
- Vue初始化
- Vue視圖數據綁定
- Vue數據變化刷新
- Vue視圖操作刷新
- 框架工具
- 基礎工具(\shared)
- 模板編譯助手
- 核心實例工具
- Web渲染工具
- 基礎原理
- dom
- string
- array
- function
- object
- es6
- 模塊(Module)
- 類(Class)
- 函數(箭頭)
- 字符串(擴展)
- 代理接口(Proxy)
- 數據綁定基礎
- 數據綁定實現
- mvvm簡單實現
- mvvm簡單使用
- vdom算法
- vdom實現
- vue源碼分析資料