- 函数定义
- 函数声明 function add () {}
- 函数表达式 var add = function () {};
- 对象实例化 var add = new Function() {};
//1.函数声明与函数表达式、对象实例化的区别
add1(1,1);
add2(1,2);
add3(1,3);
function add1(i, j){
console.log(i+j);
}
var add2 = function(i, j){
console.log(i+j);
}
var add3 = new Function("i", "j", "console.log(i+j);");
函数声明会实现声明提前,即使函数调用在函数定义之前依然可以调用
而函数表达式和函数对象实例化不行
//2.对象实例化与函数声明与函数表达式的区别
(function(){
var i = 10;
function add(j) {
console.log(i+j);
debugger;
}
add(1);
})();
(function(){
var i = 10;
var add = new Function("j", "console.log(i+j);debugger;");
// add 函数这时属于全局,所以无法获得 i
add(1);
})();
- 构造函数
// 构造函数
function Car(type,color){
this.type = type;
this.color = color;
this.status = "stop";
this.light = "off";
}
Car.prototype.start = function(){
this.status = "driving";
this.light = "on";
console.log(this.type + " is " + this.status);
}
Car.prototype.stop = function(){
this.status = "stop";
this.light = "off";
console.log(this.type + " is " + this.status);
}
var audi = new Car("audi", "silver");
var benz = new Car("benz", "black");
var ferrari = new Car("ferrari", "yellow");
// 用构造函数实例化的对象可以直接获取和修改其内部的属性
// 如 audi.type = 'toyota';
// 显然这不是好的方式,它不能实现变量的私有化
// 还有其他内置的构造函数
// Boolean、String、Number、Object、Function、Array、Date、RegExp、Error
// 比如打印出对象
console.dir(new Boolean());
// 其结果如下
console.dir(new Boolean());
VM1866:2 Boolean__proto__: Booleanconstructor: Boolean()arguments: nullcaller: nulllength: 1name: "Boolean"prototype: Booleanconstructor: Boolean()toString: toString()valueOf: valueOf()__proto__: Object__defineGetter__: __defineGetter__()__defineSetter__: __defineSetter__()__lookupGetter__: __lookupGetter__()__lookupSetter__: __lookupSetter__()constructor: Object()arguments: nullassign: assign()caller: nullcreate: create()defineProperties: defineProperties()defineProperty: defineProperty()deliverChangeRecords: deliverChangeRecords()freeze: freeze()getNotifier: getNotifier()getOwnPropertyDescriptor: getOwnPropertyDescriptor()getOwnPropertyNames: getOwnPropertyNames()getOwnPropertySymbols: getOwnPropertySymbols()getPrototypeOf: getPrototypeOf()is: is()isExtensible: isExtensible()isFrozen: isFrozen()isSealed: isSealed()keys: keys()length: 1name: "Object"observe: observe()preventExtensions: preventExtensions()prototype: Objectseal: seal()setPrototypeOf: setPrototypeOf()unobserve: unobserve()__proto__: ()<function scope>hasOwnProperty: hasOwnProperty()isPrototypeOf: isPrototypeOf()propertyIsEnumerable: propertyIsEnumerable()toLocaleString: toLocaleString()toString: toString()valueOf: valueOf()get __proto__: get __proto__()set __proto__: set __proto__()[[PrimitiveValue]]: false__proto__: ()apply: apply()arguments: (...)get arguments: ThrowTypeError()set arguments: ThrowTypeError()bind: bind()call: call()caller: (...)get caller: ThrowTypeError()set caller: ThrowTypeError()constructor: Function()length: 0name: ""toString: toString()__proto__: Object<function scope><function scope>toString: toString()arguments: nullcaller: nulllength: 0name: "toString"__proto__: ()<function scope>valueOf: valueOf()arguments: nullcaller: nulllength: 0name: "valueOf"__proto__: ()<function scope>__proto__: Object__defineGetter__: __defineGetter__()__defineSetter__: __defineSetter__()__lookupGetter__: __lookupGetter__()__lookupSetter__: __lookupSetter__()constructor: Object()hasOwnProperty: hasOwnProperty()isPrototypeOf: isPrototypeOf()propertyIsEnumerable: propertyIsEnumerable()toLocaleString: toLocaleString()toString: toString()valueOf: valueOf()get __proto__: get __proto__()set __proto__: set __proto__()[[PrimitiveValue]]: false[[PrimitiveValue]]: false
- 构造函数和普通函数的区别
本质上没有什么区别
-
构造函数的this会指向实例对象,并且this指定实例的属性 如:
this.type = type;
this.color = color;
this.status = "stop";
this.light = "off";
在原型对象上有一些公共方法 如:
Car.prototype.start = function(){
this.status = "driving";
this.light = "on";
console.log(this.type + " is " + this.status);
}
Car.prototype.stop = function(){
this.status = "stop";
this.light = "off";
console.log(this.type + " is " + this.status);
}
- 构造函数命名首字母为大写
- 函数调用 (this)
// 在每个函数中都有 this 和 arguments, this 根据调用方式不同,会绑定到不同的地方
- 构造函数调用模式
var Audi = new Car('Audi', 'silver');
this 绑定到实例化对象 Audi 上 (new 绑定) - 方法调用模式
(方法和函数的区别,方法是指绑定对象的函数,这只是一个名称上的规范)
比如:
Audi.start();
// this 绑定到调用它的对象上 - 函数调用模式
// 函数调用模式
function add(i, j){
return i+j;
}
var myNumber = {
value: 1,
double: function(){
var helper = function(){
// this 指向的是 window
this.value = add(this.value,this.value);
}
helper();
}
}
myNumber.double()
// 通过打印对象 console.dir(myNumber); value = 1;
// 解决方法是把this保存
function add(i, j){
return i+j;
}
var myNumber = {
value: 1,
double: function(){
var that = this;
var helper = function(){
that.value = add(that.value,that.value);
}
helper();
}
}
myNumber.double()
// 通过打印对象 console.dir(myNumber); value = 2;
// 注意:任何在函数内部调用的子函数 this 指向全局
- apply(call) 调用模式
var a = 2;
function foo() {
return this.a;
}
var obj = {
a: 3,
foo: foo
}
obj.foo(); // 3
foo.call(obj); // 3
var bar = obj.foo;
bar(); // 2
// arguments转数组
function add(i, j) {
var args = Array.prototype.slice.apply(arguments);
args.forEach(function(item){
console.log(item);
})
}
add(1,2,3);
// arguments.callee使用
console.log(
(function(i){
if (i==0) {
return 1;
}
return i*arguments.callee(i-1);
})(5)
);
// 递归
function factorial(i){
if (i==0) {
return 1;
}
return i*factorial(i-1);
}
// 普通递归函数跟记忆函数调用次数对比
var factorial = (function(){
var count = 0;
var fac = function(i){
count++;
if (i==0) {
console.log('调用次数:' + count);
return 1;
}
return i*factorial(i-1);
}
return fac;
})();
for(var i=0;i<=10;i++){
console.log(factorial(i));
}
// 记忆函数
var factorial = (function(){
var memo = [1];
var count = 0;
var fac = function(i){
count++;
var result = memo[i];
if(typeof result === 'number'){
console.log('调用次数:' + count);
return result;
}
result = i*fac(i-1);
memo[i] = result;
return result;
}
return fac;
})();
for(var i=0;i<=10;i++){
console.log(factorial(i));
}
// curry函数柯里化
function add(value){
var helper = function(next){
value = typeof(value)==="undefined"?next:value+next;
return helper;
}
helper.valueOf = function(){
return value;
}
return helper
}