对象介绍
创建对象的三种方式
// 字面量方式
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();
网友评论