学习js已经有一段时间了,大大小小还是能够做出一些东西来。不过觉得可惜的是,还是对js本身这门语言不是很熟悉,总有一点雾里看花的感觉,看得见,但是看不清楚。最近发现有一本关于js的叫做《忍者秘籍》的书刊,听说是jQuery作者写的,可以让初级者进阶,哇啦啦,打怪兽,加经验升级,多好的事情。于是,就有了此篇文章及其后续。闲话休谈,正事要紧!

javascript是一门函数式语言(functional language)。最重要的,在js中,函数是第一型对象(first-class object),也就是说,函数可以共处,可以将其视为其他任意类型的javascript对象。就像普通的js数据类型,函数可以被任意变量进行引用,或声明成对象字面量,甚至可以将其作为函数参数进行传递。

函数的第一型对象体现在:

1、它们可以通过字面量进行创建;

2、它们可以赋值给变量、数组或其他对象的属性;

3、它们可以作为参数传递给函数;

4、它们可以作为函数的返回值进行返回;

5、它们拥有动态创建并赋值的属性。

函数除了以上的功能外,它还包含一个功能,它们可以被调用。千万不要小瞧了函数的调用!因为不同的调用机制会产生不同的功效,特别是针对函数的this关键字。

当我们定义了一个函数,以便其他一些代码在适当的时候回头调用它,我们可以称之为回调。回调是高效利用js必不可少的一部分。

js函数是使用函数字面量(function literal)进行声明从而创建函数值的。例如:

function method(){}

一个函数的创建,由四个部分组成:

1、function 关键字;

2、函数名称,为可选。没有名称的函数称为匿名函数;

3、圆括号包含的一个以逗号分隔的参数列表,该参数列表可以为空,但是圆括号必须存在;

4、大括号包含的函数体。函数体可以为空,但大括号必须存在。

所有的函数都有一个name属性,该name属性值是该函数名称的字符串。没有名称的函数也有name属性,只是该属性值为空字符串。

//该函数的name属性值为Method
function Method(){}//通过匿名函数赋值的情况,该函数的name属性值为空字符串,因为function关键字后面没有函数名称
var method=function(){};//该函数的name属性值为method,因为该函数声明中,包含了函数名称
var fun=function method(){}

当我们声明一个函数时,我们不仅要关注该函数可用的作用域,还要关注该函数自身所创建的作用域,以及函数内部的声明是如何影响这些作用域的。

js不同于其他面向对象语言,在js中,作用域是由function进行声明的,而不是代码块。或许有的变量或函数声明于代码块,但不终结于该代码块。例如:

function method(value){//虽然变量i在for代码块中声明,但是变量i的作用域离开了该for代码块也存在,一直到method函数体结尾,下面在if代码块中声明的变量a也是一个道理for(var i=0;i<10;i++){}alert(i);//10        alert(a);//undefined    a=2;    alert(a);//2if(true){var a=1;}alert(a);//1
}

关于变量和函数声明的作用域:

1、变量声明的作用域开始于声明的地方,结束于所在函数的结尾,与代码嵌套无关。值得注意的是,只要在该函数中,变量在其声明之前,还是可以通过对其赋值进行调用,如果不对其进行赋值,那么该变量值为undefined,列子如上面method函数中的变量a;

2、命名函数的作用域是指声明该函数的整个函数范围,与代码嵌套无关。说的就是函数声明提升机制。

3、对于作用域声明,全局上下文就像一个包含页面所有代码的超大型函数。

每个声明项的作用域不仅取决于它的声明,还取决于它是变量还是函数。

在编写js代码时,我们都是称调用js函数,但是,能否应该停下来想一想,函数被调用时,到底发生了什么?

事实证明,函数调用的方式对其函数内部的代码是如何执行的,有着巨大的影响,尤其是针对this参数,这是非常重要的。

实际上,有四种不同的方式可以进行函数调用,每种方式都有它们自己细微的差别:

1、作为一个普通函数进行调用,这是最简单的形式。如:method();

2、作为一个对象的方法进行调用,支持面向对象编程。如:person.setName();

3、作为构造器进行调用,创建一个新对象。如:new Person();

4、通过apply()或call()方法进行调用。如:[].slice.call(argument,0,3)。

在研究函数调用之前,我们先来看函数的参数传递。当一个参数列表作为函数调用的一部分时,这些参数会按照函数声明里的形参声明顺序,将参数值分别赋给这些形参。第一个参数赋值给第一个形参,第二个参数赋值给第二个形参,以此类推。

如果传入的参数与形参的个数不一致,怎么办?别担心,山人自有妙计:

1、如果实际传递的参数数量大于函数声明的形参数量,超出的参数则不会配给形参;

2、如果实际传递的参数数量小于形参数量,则没有对应参数的形参会被赋值为undefined。

在参数传递的时候,有一个非常有趣且非常有用的现象,所有的函数调用都会传递两个隐式参数:arguments和this。所谓的隐式,也就意味着两个参数不会显示在函数签名里,但是它们默默地传递给函数并存在于函数的作用域内。在函数内部,它们可以像其他显示命名的参数一样使用。

arguments参数:这是传递给函数的所有参数的一个集合。该集合拥有length属性,length值为全部参数的个数。我们可以通过for循环遍历出每个参数值,也可以像访问数组一样通过索引去获取其中的某个参数值。例如argument[0]就是获取第一个参数值。在这里,请注意,arguments不是数组!arguments不是数组!arguments不是数组!重要的事情说三遍。它就像一个类数组结构。

this参数:一个函数被调用时,除了传入函数的显示参数外,名为this的隐式参数也被传入了函数。this参数引用了与该函数调用进行隐式关联的一个对象,被称之为函数上下文(function context)。请注意,js中的this依赖于函数的调用方式。

如果一个函数作为普通函数进行调用,也就是例如method()这种,一个函数名称加上圆括号的样式。以这种方式进行调用时,函数的上下文是全局上下文,也就是说隐式传入的this是window对象。

如果将一个函数作为对象的方法进行调用,例如person.setName()这种,则该person对象就变成了setName函数的上下文。也就是说一个方法所属的对象在该方法体内可以以this的形式进行引用。说得通俗一点,传入该对象方法的this是当前调用该方法的对象,也就是person。

注意:相同的函数,其函数上下文(this)会随着函数调用方式的变化而变化,而不是取决于函数是怎样声明的。因为一个函数,可以被当做普通函数调用,也可以赋值给一个对象的方法。

将函数作为一个构造器进行调用,其实它并没有什么特别的地方。只是,构造器函数的声明和其他函数有点不大一样,不同的地方是在于如何调用该函数。将函数作为构造器(constructor)进行调用,我们要在函数名称前使用new关键字,例如:new Person()。

将函数作为构造器进行调用,是js的一个超级特性,因为构造器调用时,会发生如下行为:

1、创建一个新的空对象;

2、将该新的空对象当做this参数传递给构造器函数,从而成为该构造器的函数上下文(this);

3、如果该构造器函数没有显示的返回值,则新创建的对象就会作为构造器的返回值进行返回。

请注意:构造器的目的是要创建一个新对象并对其进行设置,然后将其作为构造器的返回值进行返回。任何干扰或者不存在这种意图的函数,都不适合作为构造器函数。

我们可以用以下代码来测试:

//声明一个构造器函数
function Person(){this.showSelf=function(){return this;};
}//创建一个对象
var p=new Person();if(p===p.showSelf())alert("OK!");
else alert("Fail!");//OK!//解析以上代码
//首先声明一个构造器函数Person
//接着,用new调用构造器函数Person,并创建一个对象p//当构造器函数Person被调用时:
//1.创建一个新的空对象
//2.将新创建的对象当做this参数隐式传递给构造器函数Person。然后在Person内部,this新增了一个方法showSelf
//3.将该新创建的对象当做返回值,并赋值给p变量//p对象和p.showSelf方法返回的this指向的是同一个对象,因此它们真相等!

由于构造器的编码和使用方式不同于其他函数,除了作为构造器调用之外,通常它们也不是全部都那么有用,因此命名约定的出现是为了区别构造器和其他普通函数的方法。一般函数的命名以动词开头,比如setName、getName之类的。而构造器的名称通常是由一个描述所构造对象的名词来命名,如Person。

在函数调用的时候,js为我们提供了一种方式,就是可以显示指定任何一个对象作为其函数上下文。js中的每个函数都有apply()和call()方法。使用其中一个方法,我们都可以实现这种功能。有的同学会迷惑,为啥函数也有它们自己的方法呢?因为作为第一型对象(透个底,它是由Function()构造器创建的),函数可以像其他任何类型的对象一样,拥有属性和方法。

通过函数的apply()方法来调用函数,我们要给apply()传递两个参数:第一个是函数上下文,也就是this参数,另外一个是作为函数参数所组成的数组。call()方法与此非常类似,唯一不同的就是,给函数传入的参数是一个参数列表,而不是单个数组。如以下代码所示:

function sum(){var result=0;for(var i=0;i<arguments.length;i++)result+=arguments[i];this.result=result;
}var obj1={},obj2={};
sum.call(obj1,1,2,3,4);
sum.call(obj2,5,6);alert(obj1.result);//10
alert(obj2.result);//11//其实函数调用apply或call方法,就是显示指定传给函数的this和arguments参数

使用apply()和call()方法,我们可以选择任意对象作为函数的上下文(this)。

我们可以通过apply()或call()方法,给回调函数强制指定函数上下文,也就是this参数。如下代码所示:

//给callback强制指定其this参数为list数组的每个迭代的元素,arguments为当前迭代元素的索引
function forEach(list,callback){for(var i=0;i<list.length;i++)callback.call(list[i],i);
}var names=['小明','小花','小萌'];//回调函数的this参数就是names数组的单个元素
forEach(names,function(index){console.log("大家好,我是"+this);
});//大家好,我是小明
//大家好,我是小花
//大家好,我是小萌

转载于:https://www.cnblogs.com/williamwsj/p/7155674.html

javascript进阶笔记(1)相关推荐

  1. Javascript进阶笔记

    DOM简单学习 * 功能:控制html文档的内容*代码:获取页面的标签(元素)对象Element*document.getElementByid("id值");通过元素的id获取元 ...

  2. JavaScript进阶5-学习笔记

    文章目录 JavaScript进阶5-学习笔记 例子 JavaScript进阶5-学习笔记 参考理解:https://blog.csdn.net/hhhmonkey/article/details/1 ...

  3. JavaScript进阶4-学习笔记

    文章目录 JavaScript进阶4-学习笔记 递归 JavaScript进阶4-学习笔记 前端: 根据Ui写页面,使用vuecli+vue---测试功能---需要数据(json,array,字符串) ...

  4. JavaScript进阶3-学习笔记

    文章目录 JavaScript进阶3-学习笔记 闭包 JavaScript进阶3-学习笔记 //组件封装 什么是封装? 将冗余的代码精简化 例如:写代码:a页面有一个函数,b页面也需要这个函数,很多人 ...

  5. JavaScript进阶2-学习笔记

    文章目录 JavaScript进阶2-学习笔记 this指针 如何改变this指向 事件委托.事件冒泡 JavaScript进阶2-学习笔记 this指针 This是什么? this是Javascri ...

  6. 前端学习笔记——JavaScript进阶

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.JavaScript 面向对象 1. 面向对象编程介绍 1.1 两大编程思想 1.2 面向过程编程 1.3 面向对 ...

  7. JavaScript进阶1-学习笔记

    文章目录 JavaScript进阶1 预解析 作用域 面向对象的写法 JavaScript进阶1 预解析 //预解析 //1) console.log(a); var a = 1; //解析过程 va ...

  8. 摘自缪雪峰的博客的JavaScript个人笔记(3)

    JavaScript个人笔记 这里的内容来自缪雪峰的博客!!! 标准对象 Date 时区 RegExp 进阶 总结 JavaScript中使用正则表达式 切分字符串 分组 贪婪匹配 全局搜索 练习 J ...

  9. JavaScript—进阶篇

    JavaScript-进阶(笔记) 第1章 系好安全带,准备启航 1-1 让你认识JS 第二章 你要懂的规则(JS基础语法) 2-1 什么是变量 2-2 给变量取个名字(变量命名) 2-3 确定你的存 ...

最新文章

  1. 使用XML模板在excel进行配置
  2. android 版本控制
  3. python的工资为什么这么低-Python为什么这么火 Python岗位薪资水平如何
  4. SQL语言之执行计划(Oracle)
  5. British Journal of Management
  6. 以太坊怎么注册_以太坊2.0将至,牛市即将到来??
  7. 多数据源:spring boot+mybatisplus配置
  8. python的pwntools工具的日常使用
  9. JqueryMobile学习之二---对话框
  10. 5渲染判断_云渲染怎么收费,5大云渲染平台实测,您选对了吗?
  11. FPGA设计中遇到的奇葩问题之“芯片也要看出身”
  12. weakhashmap_Java WeakHashMap keySet()方法与示例
  13. 在CentOS上安装Docker
  14. 小白学 Python 爬虫(18):Requests 进阶操作
  15. device or resource busy问题处理
  16. 学习Photoshop的一些网站以及找素材的网站
  17. DTX编解码原理New
  18. docker--volumes,bind mounts和tmpfs mount
  19. 数据库:delete 删除语句
  20. 最全的渗透测试具体详细检测方法

热门文章

  1. vue入门到启动_一篇超完整的Vue新手入门指导教程
  2. markdown\LaTeX数学公式、数学符号、换行、等号对齐
  3. Turtlebot 3 SLAM创建地图及 Navigation导航
  4. android集成flutter闪退,flutter v1.12.13+hotfix.5 华为畅想9闪退
  5. pygame 飞机大战飞机、BOSS信息的显示
  6. 支付宝上线拼团功能 新零售线下商业地理技术运用时代来临!
  7. 如何将CAD绘图软件的语言设置为中文状态下
  8. 浅析中国移动上云的有效捷径——部署云盒子企业网盘!
  9. python基于opencv工具掌纹主线提取
  10. [UESTC1636]梦后楼台高锁,酒醒帘幕低垂