第二节:函数和对象

一、函数


JavaScript中的函数定义分为两种:声明式函数和赋值式函数。而且,函数的名称就是函数的内存地址,和变量一样,指向函数代码所在的内存区域。

// 声明式函数

function fn(name){

var msg = "你好,"+name+",我是一个函数.";

alert(msg);

}

// 赋值式函数

var fn = function(name){

var msg = "你好,"+name+",我是一个函数.";

alert(msg);

}

以上两种表达式中的fn是一样的,都是指向一个函数的指针。alert(fn)的运行结果都是:

alert(fn)之所以能够打印函数的声明语句,是因为toString()方法:

function fn(){

var msg = "你好,"+name+",我是一个函数.";

alert(msg);

}

alert(fn.toString());

运行结果是一样的。

那么toString()方法是怎样来的呢?

对于JavaScript来说,函数其实是Function类的对象。比如,我们可以用Function类直接创建上面的fn函数:

var fn = new Function("name","var msg = \"你好,\"+name+\",我是一个函数.\";\nalert(msg);");

alert(fn);

执行结果如下:

函数的执行结果也是一样的:

var fn = new Function("name","var msg = \"你好,\"+name+\",我是一个函数.\";\nalert(msg);");

fn("张三");

Function对象有length属性,可以查看函数的参数,有valueOf()方法和toString()方法,这两个方法返回的都是函数的源代码。因此,alert(fn)显示的就是函数的声明语句了。

既然函数名是指向函数的变量,那么就可以把函数作为参数传递给另一个函数。

function fn(name){

var msg = "你好,"+name+",我是一个函数.";

alert(msg);

}

function call_fn(func,name){

func(name);

}

call_fn(fn,"张三");

JavaScript的函数,使用特殊对象arguments封装了函数的参数,我们无需明确指出参数名,就能访问它们。通过属性 arguments.length可以获得函数的参数个数 。用arguments对象判断传递给函数的参数个数,即可模拟函数重载。下面是官方的一个例子。

function doAdd() {

if(arguments.length == 1) {

alert(arguments[0] + 5);

} else if(arguments.length == 2) {

alert(arguments[0] + arguments[1]);

}

}

doAdd(10);       //输出 "15"

doAdd(40, 20);    //输出 "60"

JavaScript函数中,变量的作用域,要特别注意的一点是:加var关键字的变量是函数内部的局部变量,函数执行完后,变量将销毁;但没有加var关键字的变量,将成为全局变量,函数外可以访问。

function fn(){

var x = 10;

y = 20;

alert("函数内部访问x:"+x+"\n函数内部访问y:"+y);

}

fn();

alert("函数外部访问y:"+y);

alert("函数外部访问x:"+x);

          


二、对象


JavaScript没有类的概念,只有对象定义。对象是由 new 运算符加上要实例化的对象的名字创建的。其中,要实例化的对象其实就是函数。那么,函数是怎样变成对象的呢?

先看下面这段代码。

function myobj(){

return this;

}

var f = myobj();

var o= new myobj();

alert(f);

alert(o);

我们发现,加了new运算符后,this才指向由myobj创建的对象。

而var f = myobj(),这就不是创建对象,其中的this不是指myobj创建的对象,而是代码当前上下文环境的当前对象,比如是window。

也就是说,用new运算符调用函数就创建了对象。this代表实例化之后的对象,可以显示的return,但并不需要这么做。以下代码效果是一样的。

function myobj(){

}

var o = new myobj();

alert(o);

JavaScript的Object对象与Java中的Object相似,JavaScript中的所有对象都由这个对象继承而来,Object对象中的所有属性和方法都会出现在其他对象中。

Object 对象具有下列属性:

  1. constructor:创建对象的函数(构造函数)的引用(指针)。
  2. Prototype:对该对象的对象原型的引用。对于所有的对象,它默认返回Object对象的一个实例。

还具有几个方法:

  1. hasOwnProperty(property) :判断对象是否有某个特定的属性。必须用字符串指定该属性。(例如,o.hasOwnProperty("name"))。
  2. isPrototypeOf(object) :判断该对象是否为另一个对象的原型。
  3. propertyIsEnumerable :判断给定的属性是否可以用 for...in 语句进行枚举。
  4. toString() :返回对象的原始字符串表示。对于 Object 对象,ECMA-262 没有定义这个值,所以不同的 ECMAScript 实现具有不同的值。
  5. valueOf() :返回最适合该对象的原始值。对于许多对象,该方法返回的值都与 ToString() 的返回值相同。

我们在浏览器的开发者工具的控制台输入new object()回车,可以查看上面那些Object对象的属性和方法。

Object对象也可以使用对象字面量语法来创建:var o = {};

同样,我们可以在浏览器的开发者工具中进行验证。

javascript支持后绑定,比如这样:

function obj()

{

}

var o = new obj();

o.fn = function(){

alert("hello");

}

o.fn();

所以,可以通过函数创建对象,这叫工厂方法:

function createCar(color,doors,mpg) {

var car = new Object();

car.color = color;

car.doors = doors;

car.mpg = mpg;

car.showColor = function() {

alert(this.color);

};

return car;

}

var car1 = createCar("red",4,23);

var car2 = createCar("blue",3,25);

car1.showColor();

car2.showColor();

     

比较正规一点的创建对象的方法,用构造函数法,用this代表当前对象了:

function Car(color,doors,mpg) {

this.color = color;

this.doors = doors;

this.mpg = mpg;

this.showColor = function() {

alert(this.color);

};

}

var car1 = new Car("red",4,23);

var car2 = new Car("blue",3,25);

car1.showColor();

car2.showColor();

     

构造函数法的问题是,其中的对象方法,比如例子中的showColor方法,每次new的时候都会创建一次,显然浪费内存。

可以用原型链定义对象的方法。这样,所有对象共享一个对象方法,既保证了对象属性的唯一性,也节约了内存:

function Car(color,doors,mpg) {

this.color = color;

this.doors = doors;

this.mpg = mpg;

this.drivers = new Array("Mike","John");

}

Car.prototype.showDrivers = function() {

alert(this.drivers);

};

var car1 = new Car("red",4,23);

var car2 = new Car("blue",3,25);

car1.drivers.push("Bill");

car1.showDrivers();        //输出 "Mike,John,Bill"

car2.showDrivers();        //输出 "Mike,John"

     

对象方法,只能是new之后的对象可以访问:

function obj(){

}

obj.prototype.fn = function(){

alert("hello");

}

var o = new obj();

o.fn();

但是,如果这样访问obj.fn()就会报错:

function obj(){

}

obj.prototype.fn = function(){

alert("hello");

}

obj.fn();

用函数名字直接访问的方法,我们叫函数方法,或者静态方法。

function obj(){

}

obj.fn = function(){

alert("hello");

}

obj.fn();

但javascript的静态方法,对象并不能访问,如果这样就会报错:

function obj(){

}

obj.fn = function(){

alert("hello");

}

var o = new obj();

o.fn();

还有很重要的一点,原型属性是所有对象共享,如果属性是引用类型,那么就会出现,一个对象修改了数值,其他对象相应的属性数值都会改变的尴尬局面。

function obj(){

}

obj.prototype.names = ["张三","李四"];

var o1 = new obj();

var o2 = new obj();

o1.names.push("o1添加的新的名字");

alert("o1.names:"+o1.names+"\no2.names:"+o2.names);

其实,javascript并没有真正的静态方法,只是利用javascript灵活的特性模拟实现的。

时间: 2024-10-14 05:54:44

第二节:函数和对象的相关文章

【软件构造】第二章第二节 软件构造的过程、系统和工具

第二章第二节 软件构造的过程.系统和工具 Outline 广义的软件构造过程 编程 静态代码分析 动态代码分析 调试与测试 重构 狭义的软件构造过程 构造系统:经典BUILD场景 构造系统的组件 构造过程和构造描述 Java编译工具 子目标和结构变体 构造工具 Notes ## 广义的软件构造过程 [编程(Coding)] 开发语言:如Java.C.Python 使用IDE(集成开发工具)的优势(组成) 方便编写代码和管理文件(有代码编辑器,代码重构工具.文件和库(Library)管理工具) 能

【软件构造】第三章第二节 设计规约

第三章第二节 软件规约 这一节我们转向关注"方法/函数/操作"是如何定义的,即讨论编程中的动词,规约. Outline 一个完整的方法 什么是设计规约,我们为什么需要他 行为等价性 规约的结构:前置条件与后置条件 规约的结构 可变方法的规约 规约的评价 规约的确定性 规约的陈述性 规约的强度 如何设计一个好的规约 是否使用前置条件 Notes ## 一个完整的方法 一个完整的方法包括规约spec和实现体implementation: "方法"是程序的积木,它可以被独

【软件构造】第七章第二节 错误与异常处理

第七章第二节 错误与异常处理 本节关注:Java中错误和异常处理的典 型技术--把原理落实到代码上! Outline: Java中的错误和异常(java.lang.throwable) 异常 Runtime异常与其他异常(Exception) Checked异常和unchecked异常 checked异常的处理机制 自定义异常 Notes: ## Java中的错误和异常 [Throwable] Java.lang.throwable Throwable 类是 Java 语言中所有错误或异常的超类

杨森翔:春节文化大观上编 第三章 春节古诗词 目录 第一节:春节诗词概述 一、 除夕诗词概述 二、元日诗词概述 三、 元宵诗词概述 第二节:春节古诗词拾萃

杨森翔:春节文化大观上编 第三章 春节古诗词 目录 第一节:春节诗词概述 一. 除夕诗词概述 二.元日诗词概述 三. 元宵诗词概述 第二节:春节古诗词拾萃 一.腊祭诗词 二.祭灶诗词 三.除夕诗词 四.元旦诗词 五.人日诗词 六.元宵诗词 第一节:春节古诗词概述 中国的春节,作为除旧迎新的节日,时间相当长,从年前的腊月二十三,天空中就似乎弥漫了节日的气息.这种节日的气氛,在保持传统风俗较好的地方,甚至会持续到二月二龙抬头的时候,但欢度春节的高潮,应该说是自除夕始一直到上元之夜.因此,历代歌咏和反

javascript 函数与对象

javascript中的函数是非常重要的概念,也是比较难于理解的一个知识点! 下面就来聊聊函数: JS基于对象:什么是基于对象呢?简单的说所有代码都是"对象"; 比如函数: function person(){ } person();//1 调用函数; 比如变量: var  x=5; x=6     // 2 重新为x赋值; 上面的函数和变量都是对象:所有的函数都是Function类的对象,x是Number类的对象.相当于 var x=new Number(5): 注意: functi

JavaScript学习总结(二)——闭包、IIFE、apply、函数与对象

目录 一.闭包(Closure) 1.1.闭包相关的问题 1.2.理解闭包 二.对象 2.1.对象常量(字面量) 2.2.取值 2.3.枚举(遍历) 2.4.更新与添加 2.5.对象的原型 2.6.删除 2.7.封装 三.函数 3.1.参数对象 (arguments) 3.2.构造函数 3.3.函数调用 3.3.1.call 3.3.2.apply 3.3.3.caller 3.3.4.Callee 3.5.立即执行函数表达式 (IIFE) 3.5.1.匿名函数与匿名对象 3.5.2.函数与函数

avaScript学习总结(二)——闭包、IIFE、apply、函数与对象 目录

一.闭包(Closure) 1.1.闭包相关的问题 请在页面中放10个div,每个div中放入字母a-j,当点击每一个div时显示索引号,如第1个div显示0,第10个显示9:方法:找到所有的div,for循环绑定事件. 示例代码: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>闭包</title> <style type="

理解javascript原型和作用域系列(2)——函数和对象的关系

上文(理解javascript原型和作用域系列(1)——一切都是对象)已经提到,函数就是对象的一种,因为通过instanceof函数可以判断. var fn = function () { }; console.log(fn instanceof Object); // true 对!函数是一种对象,但是函数却不像数组一样——你可以说数组是对象的一种,因为数组就像是对象的一个子集一样.但是函数与对象之间,却不仅仅是一种包含和被包含的关系,函数和对象之间的关系比较复杂,甚至有一点鸡生蛋蛋生鸡的逻辑

第二节 Java Swing中的基本容器:JFrame

第二节 基本容器:JFrame 如果要使用Swing创建一个窗口,则直接使用JFrame即可,此类事Component类的子类,常用方法如下: 小试牛刀 创建一个简单的窗口 import java.awt.*; import java.io.*; import javax.swing.*; public class JavaSwingTest { public static void main(String args[]) throws IOException{ test1(); } //创建一

C++中new和delete的背后( call edx 调用虚表内的第二个函数(析构函数))

关于 C++中new背后的行为, 以前已经写过一篇了 理解C++中new背后的行为, 但是里面也只是泛泛而谈,没有真凭实据, 下面我们从汇编的角度看C++编译器究竟在背后干了什么? 我们的代码很简单, 如下: #include <iostream> class A { public: virtual void print() { std::cout << 10; } virtual ~A() { std::cout << "~A()"; } }; c