函数是JavaScript中很重要的一个语言元素,并且提供了一个function关键字和内置对象Function,下面是其可能的用法和它们之间的关系。

function使用方式

  1. var foo01 = function() //或 function foo01()
  2. {
  3. var temp = 100;
  4. this.temp = 200;
  5. return temp + this.temp;
  6. }
  7. alert(typeof(foo01)); // function
  8. alert(foo01()); // 300

最普通的function使用方式,定一个JavaScript函数。两种写法表现出来的运行效果完全相同,唯一的却别是后一种写法有较高的初始化优先级。在大扩号内的变量作用域中,this指代foo01的所有者,即window对象。

new function()使用方式

  1. var foo02 = new function() {
  2. var temp = 100;
  3. this.temp = 200;
  4. return temp + this.temp;
  5. }
  6. alert(typeof(foo02)); //object
  7. alert(foo02.constructor()); //300
  8.  
  9. //等价于
  1. var temp = function() {
  2. var temp = 100;
  3. this.temp = 200;
  4. return temp + this.temp;
  5. }
    var foo02 = new temp(); //没有形参,可以省略圆括号 var foo02 = new temp;
  1. alert(typeof(foo02)); //object
  2. alert(foo02.constructor()); //300

这是一个比较puzzle的function的使用方式,好像是定一个函数。但是实际上这是定一个JavaScript中的用户自定义对象,不过这里是个匿名类。这个用法和函数本身的使用基本没有任何关系,在大扩号中会构建一个变量作用域,this指代这个作用域本身。(理解为实例化匿名类)

new Function()使用方式

  1. var foo3 = new Function('var temp = 100; this.temp = 200; return temp + this.temp;');
  2.  
  3. alert(typeof(foo3)); //object
  4. alert(foo3()); //

使用系统内置函数对象来构建一个函数,这和方法一中的第一种方式在效果和初始化优先级上都完全相同,就是函数体以字符串形式给出。

Function()使用方式

  1. var foo4 = Function('var temp = 100; this.temp = 200; return temp + this.temp;');
  2.  
  3. alert(typeof(foo4)); //function
  4. alert(foo4()); //

这个方式是不常使用的,效果和方法三一样,不过不清楚不用new来生成有没有什么副作用,这也体现了JavaScript一个最大的特性:灵活!能省就省。(不推荐)

注:如果构造函数没有形参,javascript构造函数调用的语法是允许省略实参列表和圆括号的。凡是没有形参的构造函数调用都可以省略圆括号

var o = new Object(); //等价于 var o = new Object;

-------------华丽的分割线-------------

javascript在用到对象时,完全没有类的概念,但是编程的世界里,无奇不有,我们却可以通过function构造出一种假想的类,从而实现javascript中类的构造。

比如,我们通过下面的方法来构造一个类:

  1. //java
  2. class Book {
  3. private String name;
  4. private double price;
  5. public Book(name,price) {this.name=name;this.price=price;}
  6. public void setName(String name) { this.name = name;}
  7. public void setPrice(double price) {this.price = price;}
  8. public String getInfo() {...}
  9. }
  10. Book book1 = new Book('java',13.3);
  11.  
  12. //javascript
  13. function Book(name,price) {
  14. this.name = name;
  15. this.price = price;
  16. this.setName = function(name) {this.name = name;};
  17. this.setPrice = function(price) {this.price = price};
  18. this.getInfo = function() {return this.name + ' ' + this.price;};
  19. }
  20. var book1 = new Book('java',13.3);

Function是由function关键字定义的函数对象的原型

在javascript中,多出了一个原型的概念。所谓原型,其实就是一个对象的本质,但复杂就复杂在,原型本身也是对象,因此,任何一个对象又可以作为其他对象的原型。Function就相当于一个系统原型,可以把它理解为一种“基本对象类型”,是“对象”这个概念范畴类的基本数据类型。除了Function之外,其实还有很多类似的首字母大写的对象原型,例如Object, Array, Image等等。有一种说法是:javascript中所有的一切都是对象(除了基本数据类型,其他的一切全是对象),所有的对象都是Object衍生出来的。

极其重要的prototype概念

prototype的概念在javascript中极其重要,它是javascript中完成上面说的“一切皆对象”的关键。有了prototype,才有了原型,有了原型,才有了javascript五彩缤纷的世界(当然,也有人说是杂乱的)。我们可以这样去理解prototype:世界上本没有javascript,上帝说要有Object,于是有了Object,可是要有Function怎么办?只需要对Object进行扩展,可是如何扩展?只需要用prototype……当然,这是乱扯的,不过在javascript中,只要是function,就一定会有一个prototype属性。实际上确实是这样

  1. Function.prototype.show = function() {...}

在原型的基础上通过prototype新增属性或方法,则以该对象为原型的实例化对象中,必然存在新增的属性或方法,而且它的内容是静态不可重载的。原型之所以被称为原型,可能正是因为这种不可重载的特质。

比如上面的这段代码,会导致每一个实例化的function,都会具备一个show方法。而如果我们自己创建了一个类,则可以通过prototype将之转化为原型:

  1. function Book(name,price) {
  2. this.name = name;
  3. this.price = price;
  4. this.setName = function(name) {this.name = name;};
  5. this.setPrice = function(price) {this.price = price};
  6. this.getInfo = function() {return this.name + ' ' + this.price;};
  7. }
  8. Book.prototype.run = function(price) {console.log(this.price)};
  9. var book1 = new Book('java',13.3);
  10. book1.run();

这时,对于book1而言,Book就是原型,而该原型拥有一个run的原始方法,所以无论实例化多少个Book,每一个实例化对象都有run方法,而且该方法是不能被重载的,通过book1.run = function(){}是无效的。

为了和其他语言的类的定义方法统一,我们可以将这种原型属性在定义类的时候,写在类的构造里面:

  1. function Book(name,price) {
  2. this.name = name;
  3. this.price = price;
  4. this.setName = function(name) {this.name = name;};
  5. this.setPrice = function(price) {this.price = price};
  6. this.getInfo = function() {return this.name + ' ' + this.price;};
  7. Book.prototype.run = function(price) {console.log(this.price)}; //写在类的构造里面
  8. }
  9. //Book.prototype.run = function(price) {console.log(this.price)};
  10. var book1 = new Book('java',13.3);
  11. book1.run();

new Function()是函数原型的一个实例化

在理解了Function原型的概念之后,再来看new Function()就显得很容易了。首先来看下我们是怎么使用这种奇特的写法的:

  1. var log=new Function('log','console.log(log)');
  2. log('hello javascript'); //hello javascript
  3.  
  4. 其实等价于
  5. function log(log){
  6. console.log(log);
  7. }
  8. log('hello javascript');//hello javascript

new Function(参数1,参数2,…,参数n,函数体),它的本意其实是通过实例化一个Function原型,得到一个数据类型为function的对象,也就是一个函数,而该变量(log)就是函数名(理解为:new Function实例化一个Function原型,得到 一个匿名函数 ,然后赋值给变量log)。

this在这类function中的指向

this在javascript中真的是无法让我们捉摸透彻。但是有一个小窍门,就是:一般情况下,this指向的是当前实例化对象,如果没有找到该对象,则是指向window。从使用上来讲,我们应该排除new Function的讨论,因为它和我们常用的函数声明是一致的。

普通的函数中this的指向

函数声明的时候,如果使用了this,那么就要看是把该函数当做一个对象加以返回,还是以仅执行函数体。普通函数执行时,我们完全没有引入对象、类这些概念,因此,this指向window。通过代码来看下:

  1. var msg;
  2. function message(msg) {
  3. this.msg = msg;
  4. }
  5. message('ok');
  6. alert(msg);

首先是声明一个函数message,在函数中this.msg实际上就是window.msg,也实际上就是代码开头的msg。因此,当执行完message(‘ok’)的时候,开头的全局变量msg也被赋值为ok。

通过function构造类时this的指向

如果function被构造为一个类,那么必然存在该类被实例化的一个过程,如果没有实例化,那么该类实际上并没有在程序中被使用。而一旦实例化,那么this将指向实例化的对象。

  1. var age = 3;
  2. var cat1 = new function() {
  3. this.name = 'Tom';
  4. this.age = 2;
  5. this.weight = function(age) {
  6. var age = age * 2;
  7. var _age = this.age * 2;
  8. return 'weight by age:' + age + '; weight by this.age:' + _age;
  9. }(this.age);
  10. this.eye = new function() {
  11. this.size = '1.5cm';
  12. this.color = 'red';
  13. };
  14. this.catching = function(mouse) {
  15. return this.name + ' is catching ' + mouse;
  16. };
  17. };
  18. alert(cat1.weight);
  19. alert(cat1.eye.color);
  20. alert(cat1.catching('Jerry'));

上面代码中标记了4处红色的this的使用。根据我们的原则,this指向实例化对象,我们来对每一个this进行分解。

首先是cat1.weight,我使用了function(){}(),直接利用猫咪的年龄进行计算得出体重返回给weight属性。

第一个this.age出现在function(){}(this.age),这个this.age实际上是一个传值过程,如果你对我之前分析function(){}()比较了解的话,应该知道,this.age实际上是和前面this.age = 2指同一个,这里的this.age的this,首先要去找它所在的function,然后看这个function是否被实例化,最后确认,确实被实例化为cat1,因此this=cat1。

第二个this.age出现在function(){this.age}()。同样,你先需要对function(){}()再次深入了解,实际上,function(){}()就是执行一个函数而已,我们前面提到了,普通函数执行中this=window,所以,这里的this.age实际上是var age = 3。

第三个this.color出现在new function(){this.color},这里就比较好玩,由于有一个new,实际上也被实例化了,只不过是对匿名类的实例化,没有类名,而且实例化仅可能出现这一次。因此,this.color的this要去找new function的主人,也就是this.eye,而this.eye的this=cat1,所以cat1.eye.color=’red’。

第四个this.name出现在function(){this.name},它出现在cacthing方法中,它既不是普通的函数执行,也不是实例化为对象,而是正常的类中的方法的声明,因此this指向要去找它所在的function被实例化的对象,也就是cat1。

小结

本文虽然讲了很多,但核心点实际上还是落在javascript的面向对象这个点上。javascript中虽然没有明确的class的概念,那是因为它首先基于type这样的基础概念,并强调一切皆对象的这种思想。如果从哲学上讲,javascript真正符合道生一,一生二,二生万物的原则。不过本文没有提到和继承相关的内容,所有解释也是我自己的一种理解方式,不代表真正的原理,读者请自己通过其他途径进行学习。

下篇转载自:https://www.cnblogs.com/pizitai/p/6427433.html

javascript 中function(){},new function(),new Function(),Function 摘录的更多相关文章

  1. JavaScript中的Date,RegExp,Function对象

    Date对象 创建Date对象 //方法1:不指定参数var nowd1=new Date();alert(nowd1.toLocaleString( ));//方法2:参数为日期字符串var now ...

  2. 前端学习 第六弹: javascript中的函数与闭包

    前端学习 第六弹:  javascript中的函数与闭包 当function里嵌套function时,内部的function可以访问外部function里的变量 function foo(x) {   ...

  3. 在 JavaScript 中使用构造器函数模拟类

    今天,我们要讲的是在 JavaScript 中使用构造器函数(construcor function)模拟类. 构造器函数简介 你可以使用 ES6 的 class 关键字来实现类,不过我建议你使用传统 ...

  4. JavaScript 中的相等操作符 ( 详解 [] == []、[] == ![]、{} == !{} )

    ECMAScript 中的相等操作符由两个等于号 ( == ) 表示,如果两个操作数相等,则返回 true. 相等操作符会先转换操作数(通常称为强制转型),然后比较它们的相等性. 在转换不同的数据类型 ...

  5. 如何理解并学习javascript中的面向对象(OOP) [转]

    如果你想让你的javascript代码变得更加优美,性能更加卓越.或者,你想像jQuery的作者一样,写出属于自己优秀的类库(哪怕是基于 jquery的插件).那么,你请务必要学习javascript ...

  6. JavaScript中函数的定义

    JavaScript中函数的定义 制作人:全心全意 在JavaScript中,函数是由关键字function.函数名加一组参数以及置于大括号中需要执行的一段代码定义的.定义函数的基本语法格式如下: f ...

  7. 通过代数,数字,欧几里得平面和分形讨论JavaScript中的函数式编程

    本文是对函数式编程范式的系列文章从而拉开了与以下延续一个. 介绍 在JavaScript中,函数只是对象.因此,可以构造函数,作为参数传递,从函数返回或分配给变量.因此,JavaScript具有一流的 ...

  8. Jquery中$(document).ready() 和 JavaScript中的window.onload方法 比较

    Jquery中$(document).ready()的作用类似于传统JavaScript中的window.onload方法,不过与window.onload方法还是有区别的.   1.执行时间 win ...

  9. javascript中的Function和Object

    写的很好,理解了很多,特此转发记录 转自:http://blog.csdn.net/tom_221x/archive/2010/02/22/5316675.aspx 在JavaScript中所有的对象 ...

  10. javascript 中的location.href 并不是立即执行的,是在所在function 执行完之后执行的。

    javascript 中的location.href 并不是立即执行的,是在所在function 执行完之后执行的. 1 function getUrl(tp) { if (tp == 'd') { ...

随机推荐

  1. thinkphp开启事物的简单方法

    使用thinkphp开启事务,ThinkPHP 3.2.2实现事务操作的方法: 开启事务: $User->startTrans() 提交事务: $User->commit() 事务回滚: ...

  2. MySQL行列转换拼接

    mysql> select TBL_ID,CREATE_TIME,LAST_ACCESS_TIME,TBL_NAME,TBL_TYPE from TBLS; +--------+-------- ...

  3. 利用反射生成JDK动态代理

    利用反射生成JDK动态代理 在Java的java.lang.reflect包下提供了一个Proxy类和一个InvocationHandler接口,通过使用这个类和接口可以生成JDK动态代理类和动态代理 ...

  4. 数据库outer连接

    left (此处省略outer) join, 左边连接右边,左边最大,匹配所有的行,不管右边 right join,右边连接左边,右边最大,匹配所有的行,不管左边 条件直接放ON后面,是先筛选右边的表 ...

  5. hdu4614 Vases and Flowers【线段树】【二分】

    Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N ...

  6. HDU 3045 - Picnic Cows - [斜率DP]

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3045 It’s summer vocation now. After tedious milking, ...

  7. tkinter 进度条

    import tkinter as tk window = tk.Tk() window.title("我的窗口") window.geometry('600x400') var1 ...

  8. 查看win信任的证书办法机构(CA机构的公钥)

    cmd mmc

  9. csrf攻击原理及如何防止csrf攻击

    CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,是一种对网站的恶意利用,通过伪装来自受信任用 ...

  10. java-JProfiler(四)-HelloWorld示例

    1.程序代码 package jProfiler; public class Test extends Thread{ public static void main(String[] args) t ...