函数详解

2019-01-15  本文已影响0人  陈裔松的技术博客

对象介绍

创建对象的三种方式
// 字面量方式
var cat = {
    'name':'Tom',
    'age':4,
    ...
}

// 构造函数方式
var cat = new Object;
cat.name = 'Tom';

// Object.create(),老版本浏览器存在兼容性问题,不推荐使用
给对象的属性赋值
cat.name = 'Tim'
cat['name'] = 'Tim'
删除对象的属性
delete cat.name
// 这里删除的是成员name的值,而不是成员name本身
// 也就是说,console.log(cat.name)的返回值是undefined,而不会报错
检测对象是否拥有某一属性
console.log('name' in cat);  // 如果有,返回true,反之返回false
console.log(cat.hasOwnProperty('name'));  // 如果有,返回true,反之返回false
遍历对象的属性
for(var p in cat){
    console.log(cat[p]);
}
// 注意这里不要用console.log(cat.p),否则会被当成对象cat里有个名字叫做p的属性

函数的本质

本质1:函数可以被调用
本质2:函数是一个对象,这是JS独有的特点
function add(num1, num2) {
    return num1 + num2;
}
add.sex = 'male';
add.setSex = function (sex) {
    this.sex = sex;
}
console.log(add.sex);    // male
console.log(add.setSex('female'));  // undefined
console.log(add.sex);  // female
console.log(add(1, 2));  // 3
var person = {};    
var add = function () {
    return 1;
};
console.log(add());  // 1
console.log(add);    // 函数本体

// 函数作为数组的一个元素
[{}, function () {
    // body...
}]

// 函数作为对象的一个值
{
    family: {},
    setName: function (argument) {
        // body...
    }
}
setTimeout(function () {
    console.log(1);
}, 1000);
setTimeout(fn, 1000);
function fn() {
    console.log(1);
}
function fn() {
    return function () {
        console.log(1);
    };
}

// 赋值给一个新函数,然后调用
var newFn = fn();
newFn();

// 直接调用
fn()();

函数的定义

方式1:字面量方式
function add() {
    // body...
}
add();
方式2:赋值表达式方式
// 一般这样写
var add = function (argument) {
    // body...
};
add();

// 这样写也是可以的
var add = function fn(argument) {
    // body...
    fn();  // fn()只能在函数内部调用
    add();  // add()在函数内部,外部都可以调用
};
add();  // add()在函数内部,外部都可以调用
fn();X  // fn()在函数外部调用是不可以的
方式3:构造函数方式
// 比较繁琐,不推荐使用
var add = new Function('num1', 'num2', 'return num1 + num2;');
// 相当于
function add (num1,num2) {
    return num1 + num2;
}
add();
区别:预解析
// 这样是没问题的
// 预解析的时候,解析器已经知道add是个函数,所以没问题
console.log(add());  // 1
function add() {
    return 1;
}
var num = 2;

// 这样是有问题的,会报错
// 预解析的时候,解析器认为add的值是undefined,所以add()会报错
console.log(add());  // 报错
var add = function () {
    return 1;
};

函数的调用

命名函数的调用
function add() {
    // body...
}
add();
匿名函数的调用
// 这样其实也相当于命名函数
var add = function () {
    // body...
};
add();
// 匿名函数自执行
// 这样是会报错的,因为以function开头的话,解析器会认为这里是个声明
function () {
    console.log(1);
}();

// 以下都是可以的,因为这里没有以function开头
var add = function () {
    console.log(1);
}();

(function () {
    console.log(1);
})();

(function () {
    console.log(1);
}());
方法的调用
// 普通的方法调用
var operation = {
    add: function (num1, num2) {
        return num1 + num2;
    },
    subtract: function (num1, num2) {
        return num1 - num2;
    }
};
operation.add(1, 1);
// DOM事件的调用
// 当用户点击的时候,浏览器会自动调用onclick方法
document.onclick = function () {
    console.log('你点击了文档!');
};
// 当然,我们也可以手动调用这个方法
document.onclick();
// 非法字符,变量作为方法名的调用
var operation = {
    add: function (num1, num2) {
        return num1 + num2;
    },
    '@': function () {  // 注意需要引号
        console.log('@');
    },
    key: function () {
        // body...
    }
};
console.log(operation.add(1, 2));
console.log(operation['@'](1, 2));  // 非法字符作为方法名,只能这样调用
var key = 'add';
console.log(operation[key](1, 2));  // 变量作为方法名,只能这样调用
// 链式调用
var operation = {
    add: function (num1, num2) {
        console.log(num1 + num2);
        return this;
    },
    subtract: function (num1, num2) {
        console.log(num1 - num2);
        return this;
    },
    '@': function () {
        console.log('@');
    },
    key: function () {
        // body...
    }
};
operation.add(1, 2).subtract(2, 1);
构造函数的调用
// 构造函数的调用
function add() {
    // body...
}

function Person() {
    // body...
}

var num = add();
var obj = new Person();  // 只有这样调用,才能称之为构造函数
间接调用
// call,apply

var name = 'xm';
var person = {};

person.name = 'xh';
person.getName = function () {
    return this.name;
};

// 共同点:call,apply里面的第一个参数是this指向
console.log(person.getName());              // xh,默认指向实例person,所以结果是xh
console.log(person.getName.call(window));   // xm,改变this指向了window,所以结果是xm
console.log(person.getName.apply(window));  // xm,改变this指向了window,所以结果是xm

// 不同点:传参方式不同
function add(num1, num2) {
    return num1 + num2;
}
console.log(add.call(window, 1, 2));    // 3,传参方式是一个一个传
console.log(add.apply(window, [1, 2])); // 3,传参方式是一个数组的方式传
// apply的用处,如果我们得到的参数是一个数组,就可以方便的调用了
function add(num1, num2) {
    return num1 + num2;
}
var datas = [1, 2];
console.log(add.apply(window, datas));

函数的参数

参数的类型
// 基本类型,比较简单,不解释
// 引用类型
var person = {};
function setPerson(obj) {
    obj.name = 'xm';
}
setPerson(person);    // 由于引用类型传递的是地址,所以函数内部的处理会改变person的值
console.log(person);  // {name: "xm"}
参数的个数
// 实参 == 形参
function add(num1, num2) {
    return num1 + num2;
}
add(1, 2);
// 实参 < 形参
function add(num1, num2 = 2) {
    return num1 + num2;
}
add(1);
// 实参 > 形参
// 使用arguments,arguments是一个类数组
function add() {
    if (arguments.length == 0) return;
    var sum = 0;
    for (var i = 0; i < arguments.length; i++) {
        sum += arguments[i];
    }
    return sum;
}
console.log(add());
console.log(add(1, 2, 3, 4, 5));
argument
// arguments.callee
// 代表函数本身,但是在严格模式下不允许使用arguments.callee
function jiecheng(num) {
    if (num <= 1) return 1;
    // arguments.callee代表函数本身,所以可以这样实现调用
    return num * arguments.callee(num - 1);
}
console.log(jiecheng(5));
console.log(jiecheng(4));

// 在严格模式下,可以用函数的小名代替arguments.callee
// 这样即使函数名(jicheng)改了,函数内部的处理也不需要修改
"use strict";
var jicheng = function fn(num) {  // fn就是函数的小名
    if (num <= 1) return 1;
    return num * fn(num - 1);
};
console.log(jicheng(5));
console.log(jicheng(4));
// 函数名.length代表函数的参数个数
function add(num1, num2) {
    if (arguments.length != add.length) throw new Error('请传入' + add.length + '个参数!');
    return num1 + num2;
}
console.log(add(1, 1));  // 2
console.log(add(1));     // 报错
什么可以作为参数
// 数字,字符串,布尔值,undefined,null,数组,对象都可以作为参数
// 甚至函数也可以作为参数
$.each({name: 'xm', sex: 'male'}, function (index, item) {
    console.log(index);
    console.log(item);
});

setTimeout(function () {
    // body...
}, 1000)

函数的返回值

// 数字,字符串,布尔值,undefined,null,数组,对象都可以作为返回值
// 甚至函数也可以作为返回值
function fn() {
    return function (argument) {
        console.log(1);
    }
}
fn()();
var newFn = fn();
newFn();
上一篇 下一篇

猜你喜欢

热点阅读