js语言精粹-第四章函数

调用方式
  1. 方法调用
var myObject = {
 value: 0,
 increment: function (inc) {
 this.value += typeof inc === 'number' ? inc : 1 ;
 }
};
myObjcet.increment();//这是调用object对象的属性,也就是的方法调用
document.write(myObject.value);

注意:this绑定对象发生在调用的时候(而非定义时的上下文),也就是说如果其他对象(eg: anotherObjcet)调用increment(),那么函数内this绑定的就是anotherObjcet。这个“超级”延时绑定,使得this可以访问不同对象的属性,也就是this得到高度复用。

  1. 函数调用
var sum = add (3, 4)

调用add时没有对象,this被绑定到全局对象,这是JavaScript设计的错误,错误的结果就是内部函数的this无法访问外部函数的this。简单的解决方案是把外部的this复制给that,内部可以访问到这个that。
js高级程序设计上的说法是,函数定义是会预先创建包含全局变量对象的作用域链保存在属性中,当调用时把局部活动对象推入执行链,(包含augument和形参),执行完毕后活动对象销毁,而闭包有所不同。闭包外部函数返回后,其作用域链会销毁,但活动对象仍会留在内存中,直到内部的匿名函数销毁后才销毁

  1. 构造器调用

如果用new来调用函数,那么背地里会创建一个连接到该函数的prototype成员的新对象,将构造函数的作用域赋给新对象(因此this会绑定到新对象上)

  1. apply调用
闭包
核心:内部函数可以访问外部函数的变量,即使外部函数被返回了。
var myObject = (function () {
  var value = 0;
  return {
    increment: function (inc) {
      value += typeof inc === 'number' ? inc : 1;
    },
    getValue: function () {
      return value;
    }
  };
}());
myObject.increment();
myObject.value
//undefined 该立即执行函数执行完毕后,返回的是包含两个方法的对象,内部变量value应该被销毁,

myObject.getValue()
//1。这里之所以能访问到value就是由于闭包的作用,返回的对象的两个方法还能访问到其外层函数的变量(作用域链),访问的就是参数本身,而不是副本
myObject.increment(2);
myObject.getValue()
//3 value在原有1的基础上加2

下一个例子很炫酷哦~~~

var fade = function (node) {
  var level = 1;
  var step = function () {
    var hex = level.toString(16);
    node.style.background = '#FFFF' + hex + hex;//改变背景颜色
    if (level < 15) {
      level += 1;
      setTimeout(step, 200);延时调用step
    }
  };
  setTimeout(step, 100);
};

fade(document.body);

1.调用fade,函数内部设置level=1,函数表达式来定义函数,调用setTimeout,并传递step函数和时间(100ms)给它,然后它返回,fade函数结束
按普通函数的理解,如果fade函数返回,那么其内部变量level应该销毁而无法访问
2.100ms后step被调用(作为函数调用?),它利用level修改背景颜色,增加level值,并且用setTimeout让他再次运行(调用自身)
3.200ms后step再次调用,这次level还用的是上次step被调用之后修改的值,说明level变量一直都在,只要fade的内部函数需要,其内部变量就会一直保留。

  • 以下是我容易混淆的闭包
var model = "zly";
var miles = 500;
function Car( model, year, miles ) {
  this.model = model;
  this.year = year;
  this.miles = miles;
  value = 0;
  var that = this
  this.toString = function () {//0.构造函数的方法,最后对绑定到new的对象上,this可以访问到外部this,但也是闭包。
    return that.model + " has done " + this.miles + " miles" + + value++ + "values";
  };  //这里如果调用两次,那value值会递增,因为访问的是同一个活动对象
  var toString = function () {//1.闭包
    return this.model + " has done " + this.miles + " miles";
  }
  var x = toString();
  console.log(x);
  var that = this;
  return {
    function () {//2.闭包 可以访问that,不可以访问this
      console.log(that.model + " has done " + this.miles + " miles");
    }
  }
  (function () {//3.闭包 这个立即执行函数可以访问that,不可以访问this
    console.log(that.model + " has done " + this.miles + " miles");
  }())
}
var civic = new Car( "Honny", 2009, 20000 );
// console.log(civic);
// var civic2 =  Car("baby", 2019, 500);
// console.log(civic2.toString3());//undifined.说明不用new调用不会产生新对象
// console.log(civic2.toString3());
// console.log(civic2.toString3());
console.log('---------');
console.log(civic.toString());
console.log(civic.toString());
// Car("baby", 2019, 500)();

总结:核心在于this指向,若未给其指定this,那么内部this只能指向全局变量,(这是js设计的一个错误)。凡是以方法而非函数定义的,this均可访问外部函数的this。
构造函数也是一般的函数,区别在于调用时加new后,会创建一个新对象,函数内this会绑定到该对象上,
该对象会连接到该函数prototype成员??
console.log (civic instanceof Car); //true

//匿名函数中定义的任何变量,都会在执行结束时被销毁?那如果里面是个闭包呢?这是我想的,实际不知道啥时候能用到,先研究一下,一般应该也不会在匿名函数里面再套个匿名函数~~
var maker = function (count) {
  return function () {//匿名函数aaa
    var a = 0;//a是匿名函数aaa的活动对象
    return{
      add: function () {
        a++;
        console.log("a++ " + a);
      }
    } 
  }
}
var per = maker(3)();//
per.add();//a++ 1
per.add();//a++ 2
var per2 = maker(3);//在这里获取了匿名函数aaa的引用
per2().add(); //a++ 1
per2().add(); //a++ 1
var maker2 = function inner () {
  var a = 0;
  return {
    set : function(b) {
      a = b;
    },
    get : function() {
      console.log(a);
    } 
  }
}
var p = maker2();
p.set(3);
p.get();//3 这就是它适用于单例模式的原因?
maker2().set(2);
maker2().get()//0 调用一次,就会产生新的对象,虽然数值一样,但是本质不一样

关于闭包的作用域链还不是很清楚,今天又花了两个小时研究了一下,收获较小,先这样吧。
闭包实际就是大函数套小函数,大函数返回了小函数作为特权函数能访问到里面的私有变量。

模块
模块的一般形式是:一个定义了私有变量和函数的函数;利用闭包创建可以访问私有变量和私有函数的特权函数;最后返回这个特权函数,或者把他们保存到一个可访问到的地方。
利用模块模式可以摈弃全局变量的使用,对于应用程序的封装,或者构造其他单例对象(?),模块模式非常有效;也可以用来产生安全的对象
var maker = function()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值