函数

函数是一组可以随时随地运行的语句。

函数是 ECMAScript 的核心。

创建函数

    function fnOne() {//具有名称的函数,函数名必须符合变量名命名规范
//可以没有符何语句
}
var fnTwo = function () {//匿名函数
};
function () {//创建匿名函数而不立即创建其引用,那么之后就没办法调用此函数
}
(function fnThree() {
})();//创建函数并立即执行一次
(function () {})();//创建匿名函数并立即执行一次

匿名函数与命名函数的区别

    fnOne();//不会出错,使用function创建的具有名称的函数在任何与之相同作用域的地方都能调用
fnTwo();//出错
var fnTwo =function () {};//因为只有执行了这个赋值语句后,fnTwo才会被创建
function fnOne() {}

函数返回值

    function fnTest() {
return "value";//使用return来返回值
alert("Hello!!!");//执行了return之后,函数就会退出
}

函数参数

    function fnTest(arg1,arg2,arg3) {
alert(arg1+"\n"+arg2+"\n"+arg3);
}
fnTest(1,2,3);
fnTest(1,2);//没有传值过去时,就会是undefined

arguments对象:在函数执行时函数内部就会有arguments对象,它包含了所有的参数,arguments的length属性报告了传入参数个数

    function fnTest() {
for (var i=0;i< arguments.length;i++) {
alert(arguments[i]);
}
}
fnTest(1,2,3);
fnTest(45);

使用arguments对象模拟函数重载

    function fnTest() {
var args = arguments;
switch (arguments.length) {
case 0 :
return "没有输入!!!";
case 1 :
return "一个参数:"+args[0];
case 2 :
return "二个参数:"+args[0]+" 和 "+ args[1];
}
}
alert(fnTest());
alert(fnTest(1));
alert(fnTest(2));

arguments对象补充:arguments对象的callee属性指向它所在的函数

    function fnTest() {alert(arguments.callee);}

闭包

闭包,指的是词法表示包括不被计算的变量的函数,也就是说,函数可以使用函数之外定义的变量。

在 ECMAScript 中使用全局变量是一个简单的闭包实例。请思考下面这段代码:

    var msg = "我是全局变量!!!";
function say() {
alert(msg);
}
say();

在ECMAScript中,在函数声明处向函数外部看到的声明的所有变量,在函数内部都能访问到它们的最终值!

    var g = "全局变量!!!";
function fnA() {
var a="A";
function fnB() {
var b="B";
alert(a);//可以访问到a
alert(c);//但不以访问c
function fnC() {
var c = "C";
alert(a+"\n"+b);//只要遵循从里向外看的原则,看到的变量都可以访问到
}
}
}
//更复杂的闭包
function fnTest(num1,num2) {
var num3 = num1+num2;
return function () {
alert("num1+num2结果为"+num3);
};
}
var result = fnTest(23,56);
result();

闭包函数只能访问变量的最终值!!!

    function fnTest(arr) {
for (var i=0;i < arr.length;i++) {
arr[i]=function () {
alert(i+" | "+arr[i]);
};
}
}
var arr = [0,1,2,3,4,5];
fnTest(arr);
for (var i=0;i < arr.length;i++) {
arr[i]();//始终输出6还有一个undefined
//因为函数退出后,i值为6,所以访问到的值只有6
}

不但在闭包中可以访问闭包外的变量值,而且还可以设置它的值

    function fnTest() {
var a=123;
return {
set:function (param) {a = param},
get:function () {return a}
};
}
var obj = fnTest();
alert(obj.get());//
obj.set(4);
alert(obj.get());//

对象,构造函数

创建一个对象

    var obj = new Object();
alert(obj);
alert(Object);//一个函数
Object();//可以直接执行
//构造函数也是一个普通的函数
function Demo() {
}
var d = new Demo();//不会出错,使用new运算符来创建对象实例
alert(d);//object

this关键字的用法

    function Demo() {
this.property = "属性!!!";
}
d = new Demo();
alert(d.property);//属性!!!

不使用new而直接执行构造函数时,this指向window

   function Demo() {
this.property = "属性!!!";
}
var d = Demo();
alert(d.property);//undefined
alert(window.property);//属性!!!

可以给构造函数传递参数,然后可以将参数赋值给对象的属性

    function Person(name,age) {
this.name = name;
this.age = age;
}
var p1 = new Person("CJ",18);

instanceof 运算符,用来判断对象是否是某个类(虽然ECMAScript中并不存在类,但我们在这里依然使用这一术语)的实例

    var str = new String("string");
alert(str instanceof String);//true
var arr = new Array();
alert(arr instanceof Array);//true
function Demo() {}
var d = new Demo();
alert(d instanceof Demo);//true

面向对象术语

一种面向对象语言需要向开发者提供四种基本能力:

  • 封装——把相关的信息(无论数据或方法)存储在对象中的能力。
  • 聚集——把一个对象存储在另一个对象内的能力。
  • 继承——由另一个类(或多个类)得来类的属性和方法的能力。
  • 多态——编写能以多种方法运行的函数或方法的能力。

ECMAScript支持这些要求,因此可被看作面向对象的。

封装与私有属性:封装并不要求私有!

    function Person(name,age) {
this.name = name;//将值存储为对象的属性即是封装
this.age = age;
}
var p1 = new Person("CJ",18);

ECMAScript目前版本并不支持私有属性,但可以通过闭包来模拟

    function Person(name,age) {
this.getName = function () {return name};
this.setName = function (param) {name=param};
this.getAge = function () {return age};
this.setAge = function (param) {age=param};
}
var p1 = new Person("CJ",18);
alert(p1.name);//undefined
alert(p1.getName());//CJ
p1.setName("XXX");
alert(p1.getName());//XXX

继承:prototype属性

ECMAScript中,继承是通过构造函数的prototype属性实现的

    function Person(name,age) {
this.name=name;
this.age = name;
}
alert(Person.prototype);//object
Person.prototype.sort = "人";
var p1 = new Person("CJ",18);
alert(p1.sort);//所有的Person对象的实例继承了sort这个属性

所有对象都有一个方法isPrototypeOf(),用来判断它是不是另一个对象的原型

    function Person() {}
var p1 = new Person();
alert(Person.prototype.isPrototypeOf(p1));//true

在ECMAScript中让一个类继承另一个类的方式比较特殊

    function ClassA() {
this.a = "A";
}
function ClassB() {
this.b = "B";
}
ClassB.prototype = new ClassA(); //让ClassB继承ClassA
var b = new ClassB();
alert(b.a);//"A",继承了属性a
alert(b instanceof ClassB);//true
alert(b instanceof ClassA);//true,因为继承,b也是ClassA的后代
alert(ClassB.prototype.isPrototypeOf(b));//true
alert(ClassA.prototype.isPrototypeOf(b));//true,ClassA.prototype也是b的原型

然而这样的继承有个注意点——

    function ClassA() {
this.a = "A";
}
function ClassB() {
this.b = "B";
}
var b = new ClassB();//先实例化ClassB
ClassB.prototype = new ClassA();//再去继承ClassA,将prototype重置为另一个对象
alert(b instanceof ClassB);//false
alert(b instanceof ClassA);//false
alert(ClassB.prototype.isPrototypeOf(b));//false
alert(ClassA.prototype.isprototypeOf(b));//false

当构造函数需要参数时

    function Person(name,age) {
this.name = name;
this.age = age;
}
function Teacher(name,age,lesson) {
this.tempMethod = Person;//对象冒充
this.tempMethod(name,age);
//当执行Person时,由于是在Teacher某个实例上调用的,所以在Person函数中的this指向了Teacher的实例
delete this.tempMethod;//删除临时方法
this.lesson = lesson;
}
ClassB.prototype =new ClassA();//始终不应在继承时放参数
var t1 = new Teacher("HUXP",18,"C#");
alert(t1.name+" | "+ this.age+ " | "+this.lesson);

事实上,对于对象冒充,ECMAScript提供了更简洁的内置方法call,在每个函数上调用,第一个参数即为要冒充的对象,剩下的是函数需要的其它参数

    function Demo(arg) {
this.name = arg;
}
var obj = new Object();
Demo.call(obj,"name");
alert(obj.name);//"name"
//使用call重写上面继承的例子
function Person(name,age) {
this.name = name;
this.age = age;
}
function Teacher(name,age,lesson) {
Person.call(this,name,age);//对象冒充
this.lesson = lesson;
}

静态属性与Function类

在ECMAScript里有个有趣的地方是,函数本身也是对象(和数组也一样),也可使用new来创建.Function构造函数至少要传两个字符串参数,可以是空字符串。除了最后一个字符串会被当做函数体语句去执行,其它参数都会作为函数参数变量名!

    var fn = new Function();//一个空函数
//创建有内容的函数
fn = new Function("arg1","alert(arg1)");//最后一个参数为执行语句的字符串,前面参数全是函数要用到的参数
//上面的代码等效于
fn = function (arg1) {alert(arg1)};//同样,由于都是赋值语句,所以要注意出现次序
fn.property ="既然是对象,那么就要以添加属性"

事实上,在构造函数上添加的属性就被称之为静态属性,它不会被实例所继承

    function ClassDemo() {
}
ClassDemo.property = new Array();
var d =new ClassDemo();
alert(d.property);//undefined
alert(ClassDemo.property);//object

Function类的实例还有其它一些方法和属性(当然,使用function关键字声明的函数也是一样的)

    function outer() {
inner();
function inner() {
alert(inner.caller);
//函数的caller属性指向调用自身的上下文函数,这里指向outer
}
}
function applyTest() {
var args = arguments;
this.name = args[0];
this.age=args[1];
}
var obj = new Object();
applyTest.apply(obj,["name",18]);
alert(obj.name);
alert(obj.age);
//apply方法与call方法类似,也用于对象冒充,只是apply方法只有两个参数
//第一个是要冒充的对象,第二个是所有参数组成的数组

javascript快速入门12--函数式与面向对象的更多相关文章

  1. JavaScript快速入门(四)——JavaScript函数

    函数声明 之前说的三种函数声明中(参见JavaScript快速入门(二)——JavaScript变量),使用Function构造函数的声明方法比较少见,我们暂时不提.function func() { ...

  2. JavaScript基础入门12 - 面向对象编程

    目录 JavaScript 面向对象编程 前言 构造函数创建对象 instanceof constructor 返回值 原型对象 关于对象的属性查找 in hasOwnProperty() JS当中实 ...

  3. Javascript快速入门(上篇)

    Javascript的熟练之路,小弟来了. JavaScript简介:JavaScript一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型.它的解释器被称为JavaScript ...

  4. JavaScript快速入门(一)——JavaScript概览

    JavaScript是什么? JavaScript的诞生 在1995年前后,当时世界上的主流带宽为28.8Kbps,现在世界平均下载带宽为21.9Mbps(数据来源于http://www.netind ...

  5. Web开发初探之JavaScript 快速入门

    本文改编和学习自 A JavaScript Primer For Meteor 和 MDN Web教程 前文 Web开发初探 概述 本文以介绍 JavaScript 为主,初学者掌握本文的内容后,将能 ...

  6. javascript快速入门21--DOM总结

    跨浏览器开发 市场上的浏览器种类多的不计其数,它们的解释引擎各不相同,期待所有浏览器都一致的支持JavaScript,CSS,DOM,那要等到不知什么时候,然而开发者不能干等着那天.历史上已经有不少方 ...

  7. javascript快速入门10--运算符,语句

    一元运算符 一元运算符只有一个参数,即要操作的对象或值.它们是 ECMAScript 中最简单的运算符. delete 运算符删除对以前定义的对象属性或方法的引用.例如: var obj = new ...

  8. javascript快速入门8--值,类型与类型转换

    原始值和引用值 在ECMAScript中,变量可以存放两种类型的值,即原始值和引用值. 原始值(primitive value)是存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量 ...

  9. javascript快速入门2--变量,小学生数学与简单的交互

    变量 对于变量的理解:变量是数据的代号.如同人的名字一样. var num;//在JavaScript中使用关键字var声明一个变量 在JavaScript中,使用上面的语法,就可以声明一个变量,以便 ...

随机推荐

  1. algorithm ch6 heapsort

    堆排序利用的是堆这种数据结构来对进行排序,(二叉)堆可以被视为一棵完全的二叉树,树的每个节点与数组中存放该节点的值得那个元素对应.这里使用最大堆进行排序算法设计,最大堆就是parent(i) > ...

  2. java 生成execl下载

    /** * execl Export */ private void createExecl(HttpServletRequest request, HttpServletResponse respo ...

  3. MySQL 多列索引优化小记

    MySQL 5.6.30 问题背景 由于爬虫抓取的数据不断增多,这两天在不断对数据库以及查询语句进行优化,其中一个表结构如下: CREATE TABLE `newspaper_article` ( ` ...

  4. python 判断质数还是合数

    while 1: s = input('请输入一个数:') s = int(s) if s == 2: print('质数') else: if s == 0 or s == 1: print('都不 ...

  5. hdu 1068(最大独立集)

    Girls and Boys Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  6. 十个技巧快速优化你的Laravel 5 程序

    性能一直是 Laravel 框架为人诟病的一个点,所以调优 Laravel 程序算是一个必学的技能. 接下来分享一些开发的最佳实践,还有调优技巧,大家有别的建议也欢迎留言讨论. 这里是简单的列表: 配 ...

  7. sublime text3插件TrailingSpaces无法使用的解决方法

    TrailingSpaces是很好用的一款插件,可以清除代码结尾打多了几个空格或Tab,对于代码洁癖绝对是个福音,我的sublime text3本来安装了这款插件,也可以正常使用,今天突然不能用了,即 ...

  8. [ThinkPHP] 模板输出 时间格式 Unix时间戳

    {$create_time|date="y-m-d",###}

  9. python3爬虫爬取网页思路及常见问题(原创)

    学习爬虫有一段时间了,对遇到的一些问题进行一下总结. 爬虫流程可大致分为:请求网页(request),获取响应(response),解析(parse),保存(save). 下面分别说下这几个过程中可以 ...

  10. 线段树+扫描线【HDU1542】Atlantis

    Description 给定一些二维空间上的矩形,求它们的面积并. 一道线段树+扫描线的板子题 然而即使我会打了,也不能灵活运用这种算法.QAQ 遇到题还是不太会. 但是这种板子题还是随随便便切的. ...