今天学习效率还是不高,this已经把我弄晕了,面向对象果然很难,重点掌握函数的四种调用模式。
一、闭包科里化应用
案例:小新闻
function update(target) {
return function(data) {
$(target).html("<h2>"+ data.title + "</h2><p>" + data.details + "</p>");
};
}
function refresh(url, callback) {
$.ajax({
url: url,
type: "POST",
dataType: 'json',
success: callback,
fail: function(er) {
console.log(er);
}
});
}
refresh("CBAData.json", update("#CBA"));
refresh("NBAData.json", update("#NBA"));
refresh("WCBAData.json", update("#WCBA"));
二、闭包的优缺点
1.缺点:
常驻内存,增大内存的开销,使用不当就会造成内存泄漏。
2. 优点:
(1)实现缓存
(2)实现封装
(3)避免污染全局对象
(4)处理逻辑的连续性
三、应用
参数复用;延迟计算/执行;提前返回
四、作用域链
1.作用:
加强变量搜索原则的记忆
2. 绘制作用域链的步骤:
(1)全局作用域 为 0 级链。将在当前作用域上的变量、对象等数据,绘制在该链上。
(2)函数可以限定作用域,在绘制过程中,只要遇到函数,就在此基础上扩展一条新俩链,级别为 当前级别 + 1;
(3)重复2步骤,直到所有函数都扩展出了新链为止。
3. 注意点:
(1)在变量搜索的时候,如果访问的是全局变量,那么会搜索整个作用域链。性能会降低。在实际开发时,可以将常用的全局对象传入局部变量内。
(2)在同级链上的变量,互相不能访问。
五、函数的四种调用模式
1. 作用:
确定this指向的。
2. 四种模式介绍
(1)普通函数执行模式:声明一个函数后,直接通过函数的名字调用
function foo(){
console.log(this); this ->window
}
foo();
(2)构造函数模式:通过new操作符创建一个对象,此时该函数的执行模式为构造函数模式
function fn(){
console.log(this); this->构造函数创建出来的对象,即f
}
var f=new fn;
(3)方法调用模式:通过对象来调用
var obj={
say:function(){
console.log(this); this->方法的调用者
}
};
obj.say();
(4)上下文模式(call/apply模式) 作用:动态改变this的指向
function print(){
console.log(this.name); this->call/apply方法的第一个参数
}
var obj={name:'tom'};
print.call(obj);
3. call和apply的区别:
(1)fn.call(thisObj, arg1, arg2, arg3, ...argN);
thisObj 在fn函数内部的this指向(必需);
arg1, arg2, arg3, ...argN 函数fn在执行时,传入的实参。(可选)
(2)fn.apply(thisObj, [array]);
thisObj 在fn函数内部的this指向(必需);
数组对象 将数组的所有元素值当做fn执行时的实参。(可选)
4. 面试题
(1)var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function() {
return function() {
return this.name;
};
}
};
alert(object.getNameFunc()()); // the window
解析:return返回的是一个匿名函数function,普通函数this指向window
(2)var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function() {
var that = this; //此时this指向object对象
return function() {
return that.name; //that也指向object对象 that.name就是My Object
};
}
};
alert(object.getNameFunc()()); // My Object
(3)var age=100;
function test() {
this.age=50;
return function () {
return this.age;
}
}
var m=new test();
console.log(m.age); // undefined
console.log(m()); // 100
var n=test();
console.log(n()); // 50
5.上下文模式应用
1. 借用方法
(1)数组合并
a.实现两个数组合并
var arr1=[1,2,3,4];
var arr2=[5,6,7,8];
arr1.push.apply(arr1,arr2);
console.log(arr1);
b.将两个数组添加到对象中
var arr1=[1,2,3,4];
var arr2=[5,6,7,8];
var o={};
arr1.push.apply(o,arr1.concat(arr2));
console.log(o);
(2)借用Math对象方法
var arr = [1, 5, 9, 20, 10];
console.log(Math.max.apply(null, arr));
(3)获取对象类型
function _type(obj) {
if(obj === null) return "null";
else if(typeof obj === "object") return /^functions*(w+)(/.exec(obj.constructor)[1].toLowerCase();
else return typeof obj;
}
console.log(_type(null)); // "null"
console.log(_type(undefined)); // "undefined"
console.log(_type([])); //"array"
console.log(_type("string")); // "string"
function foo() {}
console.log(_type(foo)); //function
(4)实现伪数组对象转换为真数组
<div>d1</div>
<div>d2</div>
<div>d3</div>
<div>d4</div>
<script>
// NodeList 伪数组对象
var doms = document.querySelectorAll('div')
// 伪数组变成真数组
var arrDom = Array.prototype.slice.call(doms);
</script>
2. 实现借用构造函数继承
function Person(name, age, gender, high) {
this.name = name;
this.age = age;
this.gender = gender;
this.high = high;
}
function Teacher(name, age, gender, high, codeNo, cellphoneNo) {
Person.apply(this, Array.prototype.slice.call(arguments, 0, 4));
this.codeNo = codeNo;
this.cellphoneNo = cellphoneNo;
}
var t = new Teacher('guojing', 18, 'boy', '226', '91248', '13813813811');
console.log(t);
3. 改变this指向
前面已经介绍,这里就不过多陈述了。
总之,无论学什么,都要静下心来,一步一个脚印踏踏实实的走下来,然后就会发现不一样的世界。姑娘,加油吧!