JavaScript 函数语法

函数就是包裹在花括号中的代码块,前面使用了关键词 function:

function functionname()
{
    // 执行代码
}

当调用该函数时,会执行函数内的代码。

可以在某事件发生时直接调用函数(比如当用户点击按钮时),并且可由 JavaScript 在任何位置进行调用。

JavaScript 对大小写敏感。关键词 function 必须是小写的,并且必须以与函数名称相同的大小写来调用函数

在调用函数时,您可以向其传递值,这些值被称为参数。

这些参数可以在函数中使用。

您可以发送任意多的参数,由逗号 (,) 分隔:

myFunction(argument1,argument2)

当您声明函数时,请把参数作为变量来声明:

function myFunction(var1,var2)
{
代码
}

变量和参数必须以一致的顺序出现。第一个变量就是第一个被传递的参数的给定的值,以此类推。

在进行函数调用的时候,不管实参的数目大于形参还是小于形参,被调用的函数都会执行;在JS中函数不介意传递进来多少个参数,也不在乎传进来的参数是什么数据类型。发生函数调用的时候可以给一个实参也可以给多个实参,之所以会这样,是因为在js中的参数在内部是用一个数组来表示。函数接收到的始终是这个数组,而不关心数组中包含哪些参数,如果这个数组不包含任何参数也无所谓,包含多个参数也没问题,在函数体内可以通过arguments(参数)对象来访问这个参数数组,从而获取传递给参数的每个参数。 arguments对象和数组对象相类似,可以通过下标来获取传入的每一个元素(第一个元素是arguments[0]);也可以使用length属性来确定传递进来多少个参数,arguments对象的长度是由传入的参数个数决定,不是由定义函数的参数的个数决定

四种调用函数的方式及this指向

1、函数调用模式,this指向的全局对象window.

实例1:

函数声明

1
2
3
4
5
function add(a,b) {
    return a+b;
}
 
console.log(add(1,2));

实例2:

函数表达式

1
2
3
4
5
var add=function (a,b) {
    return a+b;
}
 
console.log(add(1,2));

2、方法调用模式,this指向当前的对象

var o = {
    prop: 21,
    f:function() {
        return this.prop;
    }
};
console.log(o.f());

3、构造器模式,this指向新创建的实例对象,也就是这里的o

function MyClass() {
    this.a = 21;
}
var o = new MyClass();
console.log(o.a);//21

4、apply\call模式,这两个的第一参数即this,当第一个参数为null,this指向window;当第一个参数为一个对象,this就指向当前这个对象。

call和apply的作用一样,只是接受参数的方式不一样,call接受的是多个单个参数,apply接受的是参数数组。
call和apply的作用简单地可以说成,当一个对象实例缺少一个函数/方法时,可以调用其他对象的现成函数/方法,其方式是通过替换其中的this为这个对象实例,改变函数运行时的上下文。call方法的妙用:1、继承 2、改变函数运行时的this指针
例如:

function Dog(){
this.sound="汪汪汪";
}
Dog.prototype.bark=function(){
alert(this.sound);
}

现在我有另外一个cat对象:

var cat={sound:'喵喵喵'}

我也想让这个cat对象可以调用bark方法,这时候就不用重新为它定义bark方法了,可以用call/apply调用Dog类的bark方法:

Dog.prototype.bark.call(cat);

或者:

dog.bark.call(cat);

加点东西,变成一个带参数的栗子:

function Dog(){
this.sound="汪汪汪";
}
Dog.prototype.bark=function(words){
alert(this.sound+" "+words);
}
var dog=new Dog();
dog.bark("有小偷");//alert:汪汪汪 有小偷
Dog.prototype.bark.call(cat,"饿了");//alert:喵喵喵 饿了

普通函数与构造函数的区别

普通函数与构造函数相比有四个明显特点:

1.不需要用new关键字调用

    fn();

2.可以用return语句返回值

    function fn(a,b){
return a+b;
}
alert(fn(2,3));//alert:5

3.函数内部不建议使用this关键字
我们说不建议使用,当然硬要用是可以的,只是要注意这时候发生了什么。如果在普通函数内部使用this关键字定义变量或函数,因为这时候this指向的是window全局对象,这样无意间就会为window添加了一些全局变量或函数。

    function greeting(){
this.name="sheila";
alert("hello "+this.name);
}
greeting();//alert:hello sheila
alert(window.name);//alert:sheila

4.函数命名以驼峰方式,首字母小写

普通函数相比,构造函数有以下明显特点:

1.用new关键字调用

    var prince=new Prince("charming",25);

2.函数内部可以使用this关键字
在构造函数内部,this指向的是构造出的新对象。用this定义的变量或函数/方法,就是实例变量或实例函数/方法。需要用实例才能访问到,不能用类型名访问。

    prince.age;//25
Prince.age;//undefined

3.默认不用return返回值
构造函数是不需要用return显式返回值的,默认会返回this,也就是新的实例对象。当然,也可以用return语句,返回值会根据return值的类型而有所不同。

构造函数里调用return时,分两种情况:

3.1 return的是五种简单数据类型:String,Number,Boolean,Null,Undefined。
这种情况下,忽视return值,依然返回this对象。

3.2 return的是Object
这种情况下,不再返回this对象,而是返回return语句的返回值。

    function Person(name){
this.name=name;
return {name:"cherry"}
}
var person=new Person("sheila");
person.name;//cherry
person;//Object {name: "cherry"}

4.函数命名建议首字母大写,与普通函数区分开。
不是命名规范中的,但是建议这么写。

使用new关键字实例化的时候发生了什么?

以上文中的Prince()函数举个栗子:

1.第一步,创建一个空对象。

var prince={}

2.第二步,将构造函数Prince()中的this指向新创建的对象prince。
3.第三步,将prince的_proto_属性指向Prince函数的prototype,创建对象和原型间关系
4.第四步,执行构造函数Prince()内的代码

原型对象

function Person(name){
    this.name = name;
}

(google浏览器)

如上,当我们创建一个函数,系统就会为这个函数自动分配一个prototype指针,指向它的原型对象。并且可以发现,这个原型对象包含两个部分(constructor 和 __proto__)其中constructor指向函数自身。(这里形成了一个小闭环)

var p = new Person("jack");
console.log(p);

我们将该函数作为模版创建实例(new方法)的时候,我们发现创建出的实例是一个与构造函数同名的object,这个object是独立的,也就是这里的p,他只包含了一个__proto__指针(实例没有prototype,强行访问则会输出undefined),这个指针指向上面提到的构造函数的prototype原型对象,则可以得出:p.__proto__===Person.prototype

结果如下:

在查看下Object的原型对象:

通过上面的代码可以看到:

  • Object对象本身是一个函数对象。
  • 既然是Object函数,就肯定会有prototype属性,所以可以看到"Object.prototype"的值就是"Object {}"这个原型对象。
  • 反过来,当访问"Object.prototype"对象的"constructor"这个属性的时候,就得到了Obejct函数。
  • 另外,当通过"Object.prototype.__proto__"获取Object原型的原型的时候,将会得到"null",也就是说"Object {}"原型对象就是原型链的终点了

在查看下Function的对象:

结果分析 :

  • 在JavaScript中有个Function对象(类似Object),这个对象本身是个函数;所有的函数(包括Function,Object)的原型(__proto__)都是"Function.prototype"。
  • Function对象作为一个函数,就会有prototype属性,该属性将对应"function () {}"对象。
  • Function对象作为一个对象,就有"__proto__"属性,该属性对应"Function.prototype",也就是说,"Function.__proto__ === Function.prototype"
  • 对于Function的原型对象"Function.prototype",该原型对象的"__proto__"属性将对应"Object {}"

在这里对"prototype"和"__proto__"进行简单的介绍:

  • 对于所有的对象,都有__proto__属性,这个属性对应该对象的原型
  • 对于函数对象,除了__proto__属性之外,还有prototype属性,当一个函数被用作构造函数来创建实例时,该函数的prototype属性值将被作为原型赋值给所有对象实例(也就是设置实例的__proto__属性)。也就是Person.prototype===p.__proto__

1、每个函数都有prototype属性,这个属性指向函数的原型对象

2、所有对象的__proto__都指向其构造器(constructor)的prototype

举个栗子:

function Person(name){

  this.name = name;

}

var p = new Person("jack");

console.log(p.__proto__===Person.prototype);//true

console.log(p.__proto__===p.constructor.prototype);//true

3、构造函数、实例和原型对象的区别与联系

3.1 实例就是通过构造函数创建的。实例创造出来就具有constructor属性(指向构造函数)和__proto__属性(指向原型对象)

3.2 构造函数中有一个prototype属性。这个属性是一个指针,指向它的原型对象

3.3 原型对象内部也有一个指针(constructor)指向构造函数。Person.prototype.constructor=Person;

3.4 Person.prototype.__proto__语句获取原型对象的原型,将得到Object对象。所有对象的原型都将追溯到Object对象。

Person.prototype.__proto__ === Object.prototype; //true

最后上一个图,便于理解

 

JavaScript之原型、函数、实例的更多相关文章

  1. JavaScript学习笔记-函数实例

    函数实例 var p = { a:15, b:'5', f1:function(){ var self = this; console.log(self.a+self.b); f2(); functi ...

  2. Javascript时间差计算函数代码实例

    Javascript时间差计算函数代码实例 <script language="javascript"> Date.prototype.dateDiff = funct ...

  3. javascript中原型(prototype)与原型链

    javascript是一门动态语言(动态语言Dynamic Programming Language:动态类型语言,意思就是类型的检查是在运行时做的,也就是常说的“弱类型”语言),没有类的概念,有cl ...

  4. 深入理解JavaScript系列:史上最清晰的JavaScript的原型讲解

    一说起JavaScript就要谈的几个问题,原型就是其中的一个.说了句大话,史上最清晰.本来是想按照大纲式的行文写一下,但写到后边感觉其实就一个概念,没有什么条理性,所以下面就简单按照概念解释的模式谈 ...

  5. 【面试必备】javascript的原型和继承

    原型.闭包.作用域等知识可以说是js中面试必考的东西,通过你理解的深度也就能衡量出你基本功是否扎实.今天来复习一下javascript的原型和继承,虽说是老生常谈的话题,但对于这些知识,自己亲手写一遍 ...

  6. javascript的原型与继承(2)

    这是上一篇的后续. Javascript是一种基于对象的语言,遇到的所有东西几乎都是对象.如果我们想要把属性和方法封装成一个对象,应该怎么做呢: 假设我们把猫看成一个对象: var Cat = { n ...

  7. 【读书笔记】读《JavaScript模式》 - 函数复用模式之类式继承模式

    实现类式继承的目标是通过构造函数Child()获取来自于另外一个构造函数Parent()的属性,从而创建对象. 1.类式继承模式#1 —— 默认方式(原型指向父函数实例) function Paren ...

  8. javascript第二弹——函数

    什么是函数 函数是一块javascript代码,被定义一次,就可以执行和调用多次:函数也是js对象,所以也可以像对象那样操作和传递:所以我们也把函数称之为函数对象: 创建函数的几种方法 一.函数声明 ...

  9. JavaScript之Function函数深入总结

    整理了JavaScript中函数Function的各种,感觉函数就是一大对象啊,各种知识点都能牵扯进来,不单单是 Function 这个本身原生的引用类型的各种用法,还包含执行环境,作用域,闭包,上下 ...

  10. javascript 之原型理解

    最近一直在了解javascript原型的问题,也算是理解了一点,希望把我所理解的,用简单的例子和说明,让更多人清除的去理解javascript原型 1,原型 prototype 是一个什么东西 我们创 ...

随机推荐

  1. java 查找数组中最接近的一个数字

    public static Integer getNumberThree(Integer[] intarray,Integer number){ int index = Math.abs(number ...

  2. mysql中包含长字段索引的优化

    不同于oracle,在mysql的Innodb存储引擎中,对索引的总长度有限制.在mysql 5.7中(https://dev.mysql.com/doc/refman/5.7/en/innodb-r ...

  3. 【转】Sql Server查看所有数据库名,表名,字段名(SQL语句)

    -- 获取所有数据库名 select * from master..SysDatabases; -- 获取hotline数据库中所有表名 select name from hotline..SysOb ...

  4. 查找算法(2)--Binary chop--二分查找

    1. 二分查找 (1)说明 元素必须是有序的,如果是无序的则要先进行排序操作. (2)基本思想: 也称为是折半查找,属于有序查找算法.用给定值k先与中间结点的关键字比较,中间结点把线形表分成两个子表, ...

  5. 国内pip源及pip命令

    更换PIP源 PIP源在国外,速度慢,可以更换为国内源,以下是国内一些常用的PIP源. 豆瓣(douban) http://pypi.douban.com/simple/ (推荐) 清华大学 http ...

  6. LeetCode 100. Same Tree (判断树是否完全相同)

    100. Same Tree Given two binary trees, write a function to check if they are the same or not. Two bi ...

  7. Zabbix主动模式与被动模式的区别——最简单的解释

    一直搞不清楚Zabbix的主动模式和被动模式的差别,网上看到别人博客里的解释都是云里雾里的,完全搞不清.知道偶然看到了以下这个解释.就基本上明白了. Zabbix的主动模式和被动模式都是相对agent ...

  8. Vue+abp树形表格

    项目中需要用到树形表格,其他同学找了一个ZkTable,我也就跟着用了,不太好用,有更好的记得联系我.先说下缺点,如果这些不能满足你,后面也没必要看了. 缺点如下(也可能我不会用,如果你会一定记得告诉 ...

  9. 写代码如何合理使用和优化我们的机器资源(CPU、内存、网络、磁盘)

    写代码脑子一定要绷紧一根弦,认知到我们所在的机器资源是有限的.机器资源有哪些?CPU.内存.网络.磁盘等,如果不做好保护控制工作,一旦某一资源满负荷,很容易导致出现线上问题. 1 CPU 资源怎么限制 ...

  10. 前端中常见字节编码(base64、hex、utf8)及其转换

    /* * 字节编码转换 * 首先都需要转为二级制数组 (ArrayBuffer) * 然后才能转换对应的编码字符 * 前端常见编码: * base64:就是将二进制转为字符串,将每6个字节转为一个特定 ...