目 录
5.1 Javascript定义一个函数一般有如下三种方式: 7
JavaScript 是世界上最流行的脚本语言, JavaScript 是属于 web 的语言,它适用于 PC、笔记本电脑、平板电脑和移动电话,相对于Web的编程的客户端JavaScript主用于用:修改网页的内容(HTML 定义),更新了网页的布局(CSS 描述),影响 网页的行为(JavaScript事件),作为一个初学者的总是那么的“杂而乱”(特别对于原来一直应用C++,C#,java等语上有些观念上差别)和实际应用的JavaScript差别很大,本文作为自己学习JavaScript的一些总结和理会
在JavaScript中基本申明变量使用的关键字都是var,这点与其他的编程语言不尽相同,但是JavaScript亦含有五种基本的数据类型(也可以说是简单数据类型),和两种复杂数据类型, 对JavaScript是松散类型的,因此需要有一种手段来检测给定变量的数据类型——typeof就是负责提供者方面信息的操作符
- "undefined"——如果这个值未定义
var car;
alert(typeof(car)); //undefined
- "boolean"——如果这个值是布尔值
var btrue =true;
alert(typeof(btrue)); //bolean
- "string"——如果这个值是字符串
var sName ="li min";
alert(typeof(sName)); //string
- "number"——如果这个值是数值
var sNum =30.0;
alert(typeof(sNum)); //number
- "Object"——数组,对像,null
var arrNum = new Array(2,4);
alert(typeof(arrNum)); //object
var a = null;
alert(typeof(a)); //object
var car = new Object();
car.color ="red";
alert(typeof(car)); //object
- "function "——函数类型
function GetSum(a,b)
{
return a+b;
}
alert(typeof(GetSum)); //function
- "undefined"——类型转换
console.log(Boolean(undefined)) //false
console.log(Number(undefined)) //NaN
console.log(String(undefined)) //:'undefined'
- "boolean"——类型转换
console.log(Number(true)) //1
console.log(Number(false)) //0
console.log(String(true)) //'true'
console.log(String(false)) //'false'
- "string"——如果这个值是字符串
console.log(Number('a')) //Nan
console.log(Number('0')) //0
console.log(Boolean('3')) //true
console.log(Boolean('0')) //true
console.log((1).toString()) //1
console.log(true.toString()) //true
- "number"——如果这个值是数值
console.log(parseFloat('a')) //Nan
console.log(parseInt('0')) //0
console.log(parseFloat('1.2')) //1.2
console.log(parseInt('1.2')) //1
ECMAScript变量包含两种不同类型的值:基本类型值、引用类型值
- 基本类型值:指的是保存在栈内存中的简单数据段, 从一个变量向一个变量复制时,会在栈中创建一个新值,然后把值复制到为新变量分配的位置上,改变源数据不会影响到新的变量(互不干涉)
- 引用类型值:指的是那些保存在堆内存中的对象,意思是,变量中保存的实际上只是一个指针,这个指针指向内存堆中实际的值, 将指针复制到栈中未新变量分配的空间中,而这个指针副本和原指针执行存储在堆中的同一个对象,复制操作结束后,两个变量实际上将引用同一个对象;因此改变其中的一个,将影响另一个
- 特别注意
function setName(obj) {
obj.name = "ABC";
obj = new Object();
obj.name = "BCD";
}
var person = new Object();
setName(person);
alert(person.name); // ABC
- apply与call函数
都是为了改变某个函数运行时的 context 即上下文而存在的,换句话说,就是为了改变函数体内部 this 的指向
- call 方法:call([thisObj[,arg1[, arg2[, [,.argN]]]]]), 参数:thisObj可选项。将被用作当前对象的对象。arg1, arg2,,,argN可选项。将被传递方法参数序列, 如果没有提供 thisObj 参数,在非严格模式下当我们第一个参数传递为null或undefined时,函数体内的this会指向默认的宿主对象,在浏览器中则是window
var test = function() {
console.log(this === window);
}
test.apply(null); //true
test.call(undefined);//true
改变上下文传入参数
var foo = {
name: "mingming",
logName: function() {
console.log(this.name);
}
}
var bar = {
name: "xiaowang"
};
foo.logName.call(bar); //xiaowang
- apply方法: Function.apply(obj,args)方法能接收两个参数obj:这个对象将代替Function类里this对象args:这个是数组,它将作为参数传给Function(args-->arguments)
function Person(name, age) { //定义一个类,人类
this.name = name; //名字
this.age = age; //年龄
this.sayhello = function() {
alert("hello")
};
}
function Print() { //显示类的属性
this.funcName = "Print";
this.show = function() {
var msg = [];
for(var key in this) {
if(typeof(this[key]) != "function") {
msg.push([key, ":", this[key]].join(""));
}
}
alert(msg.join(" "));
};
}
function Student(name, age, grade, school) { //学生类
Person.apply(this, arguments);
Print.apply(this, arguments);
this.grade = grade; //年级
this.school = school; //学校
}
var p1 = new Person("jake", 10);
p1.sayhello();
var s1 = new Student("tom", 13, 6, "清华小学");
s1.show();
s1.sayhello();
alert(s1.funcName);
这个属性是指向一个对象的引用,这个对象称为原型对象,原型对象包含函数实例共享的方法和属性,也就是说将函数用作构造函数调用(使用new操作符调用)的时候,新创建的对象会从原型对象上继承属性和方法
- 函数(类)私有变量和私有方法:
function Obj() {
var a = 0; //私有变量
var fn = function() { //私有函数
}
}
var o=new Obj();
console.log(o.a); //undefined
console.log(o.fn); //undefined
- 函数(类)静态变量和)静态方法:
function Obj(){
}
Obj.a=0; //静态变量
Obj.fn=function(){ //静态函数
alert(Obj.a);
}
console.log(Obj.a); //0
console.log(typeof Obj.fn); //function
Obj.fn();
var o=new Obj();
console.log(o.a); //undefined
console.log(typeof o.fn); //undefined
o.fn();//系统报错
- 函数(类)实例变量和实例方法:
function Obj() {
this.a = []; //实例变量
this.fn = function() { //实例方法
}
}
console.log(typeof Obj.a); //undefined
console.log(typeof Obj.fn); //undefined
var o = new Obj();
console.log(typeof o.a); //object
console.log(typeof o.fn); //function
- prototype函数(类)属性、方法是能够共享(须必定义在函数外面)
function Person(name) {
this.name = name;
}
Person.prototype.share = [];
Person.prototype.printName = function() {
alert(this.name);
}
var person1 = new Person('Byron');
var person2 = new Person('Frank');
person1.share.push(1);
person2.share.push(2);
console.log(person2.share); //[1,2]
-
- Javascript定义一个函数一般有如下三种方式:
- 函数关键字(function )语句:
function fnMethodName(x) {
alert(x);
}
- 函数字面量(Function Literals):
var fnMethodName = function (x) {
alert(x);
}
- Function()构造函数:
var fnMethodName = new Function('x', 'alert(x);')
上面三种方法定义了同一个方法函数fnMethodName,第1种就是最常用的方法,后两种都是把一个函数复制给变量fnMethodName,而这个函数是没有名字的,即匿名函数。实际上,相当多的语言都有匿名函数。
-
- 函数字面量和Function()构造函数的区别
虽然函数字面量是一个匿名函数,但语法允许为其指定任意一个函数名,当写递归函数时可以调用它自己,使用Function()构造函数则不行
var f = function fact(x) {
if(x <= 1)
return 1;
else
return x * fact(x - 1);
};
var i= f(4)
console.log(i); //24
- &bsp; 错误模式: 其无法工作,浏览器会报语法错
function() {
alert(1);
}
();
- 函数字面量:首先声明一个函数对象,然后执行它
(function() {
alert(1);
})();
- 优先表达式:由于Javascript执行表达式是从圆括号里面到外面,所以可以用圆括号强制执行声明的函数
(function() {
alert(2);
} ());
- Void操作符:用void操作符去执行一个没有用圆括号包围的一个单独操作数
void function() {
alert(3);
}
()
对于javascript函数重载这个概念,参考书籍上多多少少都会提及,也就是从语言角度来说,javascript不支持函数重载,不能够定义同样的函数然后通过编译器去根据不同的参数执行不同的函数
- 参数数量重载
function f() {
var len = arguments.length;
if(1 == len) {
var length = arguments[0];
f1(length);
} else {
var length = arguments[0];
var width = arguments[1];
f2(length, width);
}
}
function f1(length) {
alert("高为:" + length);
}
function f2(length, width) {
alert("高为:" + length + ",宽为:" + width);
}
f(4);
f(4, 8);
- 参数类型重载
function talk(msg) {
var t = typeof msg;
if(t == "string") {
talk_stirng();
} else if(t == "number") {
talk_number();
}
}
function talk_stirng() {
alert("It's a string");
}
function talk_number() {
alert("It's a number");
}
talk(10); //It's a string
talk("demo"); //It's a number
-
- 回调函数
function foo() {
var a = 10;
return function() {
a *= 2;
return a;
};
}
var f = foo();
f(); //return 20.
f(); //return 40.
f(); //return 80.
函数在外部调用,依然可以访问变量a。这都是因为javascript中的作用域是词法性的。函数式运行在定义它们的作用域中(上述例子中的foo内部的作用域),而不是运行此函数的作用域中。只要f被定义在foo中,它就可以访问foo中定义的所有的变量,即便是foo的执行已经结束。因为它的作用域会被保存下来,但也只有返回的那个函数才可以访问这个保存下来的作用域。返回一个内嵌匿名函数是创建闭包最常用的手段。