Note three points when using functions in js:
1. When a function is called, it runs in the syntax environment when it was declared. ;
2. The function cannot run by itself. It is always called by the object. When the function is running, the this pointer in the function body points to the object that calls the function. If the object is not explicitly specified when calling the function, this points to window by default (strict Except mode, this article does not cover strict mode);
3. A function is an object type data with executable code.
1. Declare function
1. Use the function keyword
return a b;
}
function(a,b){ return a b;} The anonymous function itself cannot be saved. Since the function is a kind of object data in js, the anonymous function can be assigned to a variable to save it.
var myfun = function(a,b){ return a b;}
3. Use the function constructor Function //Note that the first letter is capitalized
Function is a function built into js. It is the constructor of all function objects. (Other data objects also have their own built-in constructors, such as Number, Object, etc. The constructors of these constructors are Function, because they are all functions).
var myfun = new Function('a,b','return a b;'); The last parameter is the function body, and the previous parameters are the formal parameter names of the function. The number is variable because strings are required. Construct by passing parameters. This method of writing is very inconvenient when the function is long and is rarely used. Maybe you will use it to construct a specific return value to replace the eval function.
It should be noted that both global variables and global functions can be regarded as attributes of the window object. If there are functions and variables with the same name, only one can take effect (actually there is only one attribute). Try the following code.
alert(window.a); //You can also access the properties of the window object without writing the window
var a=1;
alert(window.a);
func1(){
alert(1);
}
alert(func1); //pop up func1(){alert(2);}
func1(){ //This is the last declared func1, subject to this function
alert(2);
}
alert(func1); //pop up func1(){alert(2);}
var func1 = function(){ //Note, this is variable assignment, not function declaration
alert(3);
}
alert(func1); //Pop up function(){alert(3);}
}
(function fun(){ });
alert(fun); //error But even in IE8, the named function in the expression cannot override the variable with the same name:
var fun = 1; //This variable cannot be overwritten by the function name in the function expression
var f = function fun(){};
alert(f); //function fun(){ };
alert(fun); //1
if(fun = function (){}){
alert(fun); // ok, a variable is declared here, which stores an anonymous function
}
js functions are reference objects
var a = function(){};
var b=a;
b.x=2;
alert(a.x); //2
2. Function parameters
The js function does not check whether the number of parameters passed in when the function is called is consistent with the number of formal parameters when it is defined. Generally, the number of parameters that can be received when a js function is called is 25. Of course, different browsing The processors may be different, and the ECMAScript standard does not regulate this.
If you are not sure how many parameters are passed in when calling a function, you can use the arguments object of the function.
arguments is a bit like an array, arguments.length is the number of parameters passed in, arguments[0] is the first parameter, arguments[1] is the second parameter, and so on...
The length attribute of the function object: This attribute is rarely used, and few people even know that the length attribute of the function is the number of formal parameters when the function is defined.
alert(arguments.length); //The actual number of parameters passed in when popping up the call
alert(arguments[0]); //Corresponding parameter a
return a b;
}
alert(myfun.length); //The number of formal parameters, 2
Note: If a subfunction with the same name as the formal parameter is declared inside the function (in the same scope, the function with the same name takes effect when the variable is not assigned a value), the corresponding value of arguments will also be modified. However, if the same name is declared using var in the scope The variable will not cause the parameter value of arguments to be replaced by the function (but firefox will still replace it).
The js function uses the return statement to return a value.
All data types can be used as return values of functions (including functions), and js functions can also have no return value.
4. Function call
The function itself will not run. When it runs, there is always an object that calls it.
By default, in any syntax environment, if the calling object of the function is not explicitly specified, the function is called through the window object. At this time, the this pointer in the function body points to the window object.
alert(this);
return a b;
}
myfun(1,2); // Call the function and pass in 2 parameters, which correspond to the formal parameters a and b respectively. When calling the function, if the number of parameters passed in exceeds the formal parameters, you can only use Arguments are received with subscripts.
There are three calling object methods for explicitly specifying functions:
1. If a function is assigned as an attribute value of an object, the function can only be accessed through the object (but it does not mean that the function can only be called by the object). The method of calling the function through the object is similar Called as a method in an object-oriented programming language (in fact, it is also customary to use the name method in js).
obj.fun=function(a,b){
alert(this); //pop this pointer
return a b;
} //Object attribute value is function
alert(obj.fun);//Access the fun function. This function can only be accessed through this object
obj.fun(1,2); //Call the fun function through the obj object, and the obj object will pop up. This method is also called calling the fun method of the obj object.
alert(this);
return a b;
}
var obj={};
fun.call(obj,1,2); //Call the fun function through the obj object and pass in 2 parameters. The pop-up pointer is the obj object.
var obj2={};
obj2.fun2 = function(a,b){ //The attribute fun2 of the obj2 object is a function
alert(this);
return a b;
};
obj2.fun2.call(obj,1,2); //Call the function stored in the fun2 attribute value of the obj2 object through the obj object. The pop-up this pointer is the obj object
//Relatively hidden method call: array calls a function [9, function(){ alert(this[0]); }][1]();
//The following methods of calling functions using window objects are equivalent
fun(1,2);
window.fun(1,2); //If the fun function is a global function
fun.call(window,1,2);
fun.call(this,1,2); //If this code is in the global environment (or within the function body called by the window object), because of this syntax This in the environment points to the window object.
func.call(); //If the function does not need to pass parameters
func.call(null,1,2);
func.call(undefined,1,2);var name = "window ";
function kkk(){
console.log(this.name); // not ie
}
kkk(); //window
kkk.call(kkk); //kkk function was called by itself
getData:function(){
var host = this; //Save the reference of the obj object
$. post(url,{param:"token"},function(dataBack){
host.data = dataBack;
3. Apply method call:
The only difference between the apply method and the call method is the method of passing function parameters.
obj2.fun2.call(obj,1,2); Change to apply method is obj2.fun2.apply(obj,[1,2]);
apply uses an array-like method to pass parameters. In addition to arrays, you can also use arguments and HTMLCollection to pass parameters, but arguments are not arrays, such as:
var obj={};
function fun_1(x,y){
function fun_2(a,b){
return a b;
}
fun_2.apply(obj,arguments); //Use the arguments object of fun_1 to pass parameters, which actually receives x, y
} There are 2 problems with applying parameters in IE8 and browsers below IE8
In call and apply calls, if scalar data (true/false, string, number) is passed in, the function will wrap the basic data they passed in into an object when running, and then point this to the wrapped object. Try Try the code below.
function a(){
alert(typeof this);
alert(this.constructor);
alert(this);
}
a.call(false);
a.call(100);
a.call('hello');
You can even use this feature to pass parameters, but this usage is not recommended:
function a(){ alert(1 this); } //The object automatically performs type conversion during operation
a.call(100); //101
4. Function as object constructor
When a function uses the new operation as an object constructor, this points to the newly constructed object. If the return value of the constructor is not an object other than null, the constructor will return the object pointed to by this after running, otherwise it will return to the original definition. object.
this.a = 1;
this.b = 3;
console.log(this); //{a:1,b:2}
// return {a:999}; //With this step, it will return {a:999}
}
var obj = new Fun(); //obj = {a:1,b:2}, if there are no parameters, it can also be written as var obj = new Fun;
The variable scope of js is at the function level. There is no block-level scope in js similar to the c language.
The top-level scope of the js programming environment is the scope under the window object, which is called the global scope. The variables in the global scope are called global variables.
Variables within a js function cannot be accessed outside the function, but variables outside the function can be accessed within the function. Variables within the function are called local variables.
JS functions can be nested. The nesting of multiple functions constitutes the nesting of multiple scopes. This is called the scope chain of JS.
The variable access rules of js scope chain are: if the variable to be accessed exists in the current scope, use the variable of the current scope, otherwise search in the upper scope until the global scope, if not found, The variable is undeclared.
Note that the declaration of variables is completed during the code parsing period. If the declaration and assignment statement of the variable in the current scope are written after the variable access statement, the js function will think that the variable to be accessed already exists in the current scope and will no longer affect the upper level. Domain lookup, however, since the variable assignment occurs during code runtime, the variable accessed will be undefined.
For example:
function out(){
var a=1;
var b=2;
function fun(){
alert(a); //undefined
var a=10;
alert(a); //10
alert(b); //2
alert(c); //1000
}
fun();
}
out();
The use of anonymous functions is very important in js. Since all data in js are objects, including functions, functions are often used as parameters or return values of another function.
If the anonymous function is not saved, it will be released from memory after running.
The way to call an anonymous function is to directly place the anonymous function in parentheses instead of the function name. Such as:
(function(a,b){ return a b;})(1,2); //Declare and execute the anonymous function, passing in two parameters during runtime: 1 and 2
//or
(function(a,b){ return a b;}(1,2));
//The following way of writing is wrong:
function(a,b){ return a b;}(1,2);
Since the semicolon at the end of the statement in js can be omitted, the js engine will think that function(a,b){ return a b;} is the end of a statement, so the anonymous function is only declared and not called. If the statement does not pass parameters ( 1,2) written as () will also cause errors. Empty brackets in js are a grammatical error.
The following way of writing is correct.
var ab = function(a,b){ return a b;}(1,2); // ab=3
When js parses grammar, if an expression appears in an assignment operation or operator operation, it is a "greedy match" (try to evaluate as much as possible)
function(t){ return 1 t;}(); //error
var f = function(t){ return t 1;}(); // ok
~ function(t){return t 1;}(); //ok
function(t){return t 1;}(); //ok
If you just want to assign an anonymous function to a variable, remember to add a semicolon after the assignment statement. Otherwise, if it is followed by parentheses, it will become a function call, especially between the parentheses and the end of the function. This error is often difficult to find when multiple lines are separated by spaces.
In actual development, anonymous functions may return in the form of operation values. This situation may not be easy to see, such as
var a =1;
var obj = {a:2,f:function(){ return this.a;}};
(1,obj.f)(); //1 The comma expression returns an anonymous function. When this anonymous function is called, thsi in the function body points to window
Declaring and immediately running an anonymous function is called a "self-executing function". Self-executing functions are often used to encapsulate a piece of js code. Due to the characteristics of function scope, variables within a self-executing function cannot be accessed externally. Code placed within the function will not affect external code, thus avoiding variable pollution. JS development can easily cause variable pollution. Code developed by other coders is often introduced during development. If different coders define global variables or functions with the same name but different meanings, variable pollution occurs. Variables with the same name appear in the same scope. or functions, the later ones will overwrite the earlier ones.
(function(){
//Your own code....
})(); Anonymous functions can also release memory in time: because the variables are declared within the anonymous function, if these variables are not referenced outside the anonymous function, then the function is finished running, and the variables inside occupy The memory will be released immediately.
The name of the function: In browsers such as Firefox, the function has a name attribute, which is the function name of the function, but this attribute does not exist in IE. In addition, the name of the anonymous function is empty.
var a=function(){}
alert(a.name); //undefined, a is a variable that stores an anonymous function
function b(){}
alert(b .name); //b ,but undefined for IE
7. When a function is called, it runs in the environment in which it was defined
No matter where the function is called or by whom, it cannot change the syntax environment when it is declared, which determines the running environment of the function
var inerFun=null;
function fun1(){
alert(x);
}
function holder(){
var x = 100;
var fun2 = fun1;
inerFun = function(){ alert(x);}
fun1(); //99
fun2();//99
inerFun(); //100
}
holder();
fun1(); //99
inerFun(); //100
//Another example:
var x = 100;
var y=77;
var a1={
x:99,
xx:function(){
//var y=88; / /If you comment this variable, y will be the global variable 77
alert(y); //Without this pointer, the object calling the function cannot affect the value of y. When the function is running, it will step by step in the scope chain from here. Search value
alert(this.x); //Using this pointer, calling function
}
}
a1.xx();
a1.xx.call(window);
var jj = a1.xx;
jj(); //The effect is the same as a1.xx.call(window); //Try the following code
var x=99;
function xb(){
this.x=100;
this.a = (function(){return this.x}).call(this); / /new is executed, the anonymous function is called by the instantiated object
this.b = (function(){return this.x})(); //new is executed, the anonymous function is called by window
this.method = function(){return this.x;}
}
var xbObj = new xb();
console.log(xbObj.x);
console.log(xbObj.a);
console.log(xbObj.b);
console.log(xbObj.method());
1. The object calling the function (or the method of calling the function) determines who the this pointer in the function body points to when the function is running
2. The syntax environment when the function is declared determines the access permissions when the function is run
3. The syntax environment of the function call statement determines whether and when the function can really be called (only if the function is visible in a certain syntax environment, this function can be called)
When the function is running, an arguments object is generated to access the parameters passed into the function. arguments has an attribute that can point to the function itself: arguments.callee.
When a function is running, the caller attribute of the function can point to the function where the function call statement is located. For example, function a is called within the body of function b, then when function a is running, a.caller points to function b. If function a If called in the global environment, a.caller=null
The values of arguments and a.caller are directly related to each call of the function. They are generated when the function is running and can only be accessed within the function body.
In IE8 and below browsers, the arguments.caller in a function (this attribute is removed after IE9) points to the arguments when a.caller is executed (arguments.caller.callee === a.caller),
7. Function calls in real-time string parsing: eval(), new Function(), setTimeout(), setInterval()
eval() and window.eval()
var obj = Objinit ();
var param = 'outerParam';
console.log(param,obj.getParam()); //outerParam 123
obj.execute('param = 456');
console.log(param,obj.getParam()); //outerParam 456
obj.setCallback(function(){ eval("param = 8888")});
obj.fireCallback();
console.log(param,obj.getParam()); //8888 456
obj.setCallback(function(){ eval("eval(param = 9999)")});
obj.fireCallback();
console.log(param,obj.getParam()); //9999 456eval()
IE 中 ,window.execScript(); 相当于 window.eval()
new Function()、setTimeout()、setInterval() 的第一个字符串参数所解析得到的代码,都是在顶级作用域执行。
八、函数闭包
要理解函数闭包,先了解 js 的垃圾自动回收机制。
number、string、boolean、undefined、null 在运算和赋值操作中是复制传值,而对象类型的数据按引用传值,
js 的同一个对象型数据可能被多次引用,如果某个对象不再被引用,或者两个对象之间互相引用之外不在被第三方所引用,浏览器会自动释放其占用的内存空间。
函数被引用:函数被赋为其他对象的属性值,或者函数内部定义的数据在该函数外被使用,闭包的形成基于后一种情形。
function fun(){
var a =1;
f = function(){ return a;};
}
fun(); //产生一个闭包
f(); // 闭包中 a=2
f(); // 闭包中 a =3 ,模拟静态变量
产生闭包的关键是,一个在函数 A内的声明的函数 B被传出 A 之外,并且 B 函数内使用了在 函数A 内生成的数据(声明或按值传参),
函数B传出函数A之外的方式有多种,如:
return {a:123,b:456, c: function(){ return a;} };
}
var f = fun();
f.c(); //a=2
广义上来说,函数运行时都会形成闭包,没有数据在函数外被引用时,闭包的生命周期很短:函数执行完毕即释放。
闭包的独立性:即使由同一个函数产生的多个闭包也是相互独立的
var a =1;
return function(){ return a;};
}
var f1 = fun(); //一份闭包
var f2 = fun(); //另一份闭包
alert(f1()); //2
alert(f1()); //3
alert(f2()); //2
alert(f2()); //3
In js oop programming, closures can be used to simulate private members and construct single classes
//Private method
function setName(name){
myname=name;
}
//Private method
function setVal(val){
myVal=val;
}
//Call the internal private method when executing new to construct the object
setName(name);
setVal(val);
//Public method
this.getName=function(){
return myName;
}
this.getVal=function(){
return myVal;
}
}
var obj = new MakeItem("name",100);
obj.myname; //undefined Private properties cannot be accessed from outside
obj.getName(); //ok
var instance = null; //在闭包中保存单体类的实例
var args = null;
var f = function(){
if(!instance){
if(this===window){
args = Array.prototype.slice.call(arguments,0);
instance = new arguments.callee();
}else{
this.init.apply(this,args||arguments);
instance = this;
}
}
return instance;
};
f.prototype = {
init:function(a,b,c){
this.a = a;
this.b = b;
this.c = c;
this.method1 = function(){ console.log("method 1"); };
this.method1 = function(){ console.log("method 1"); };
console.log("init instance");
}
};
f.prototype.constructor = f.prototype.init;
return f;
})();
//单体的使用
var obj1 = Singleton(1,2,3);
var obj2 = new Singleton();
var obj3 = new Singleton();
console.log(obj1===obj2,obj2===obj3); //true
console.log(obj1);
//一个单体类声明函数
var SingletonDefine= function(fun){
return (function(){
var instance = null;
var args = null;
var f = function(){
if(!instance){
if(this===window){
args = Array.prototype.slice.call(arguments,0);
instance = new arguments.callee();
}else{
fun.apply(this,args||arguments);
instance = this;
}
}
return instance;
};
f.prototype = fun.prototype;
f.prototype.constructor = fun;
return f;
})();
};
var fun = function(a,b,c){
this.a = a;
this.b = b;
this.c = c;
this.method1 = function(){ console.log("method 1"); };
console.log("init instance");
};
fun.prototype.method2 = function(){ console.log('method 2'); };
//Single class declaration function usage
var Singleton = SingletonDefine(fun);
var obj1 = Singleton(8,9,10);
var obj2 = new Singleton();
var obj3 = new Singleton(3,2,1);
console.log(obj1===obj2,obj2===obj3);
console.log(obj1);
//console.log(obj1.toSource()); //firefox
obj1.method1();
obj1.method2();
In IE 6, circular references to non-native js objects (DOM, etc.) will cause memory leaks. When using closures, be careful when using non-js native object references.
function fun(){
var node = document.getElementById('a');
node.onclick = function(){ alert(node.value); };
node = null; //Break circular references to prevent memory leaks
node saves DOM objects, which exist outside fun (and always exist, even if deleted, they are only removed from the document tree). After fun is executed, a closure is generated, which also constitutes a circular reference between the DOM object and the callback function ( node-function-node), a memory leak occurs under IE 6.