js原型、闭包、apply()

来源:互联网 发布:JS中nan==nan 编辑:程序博客网 时间:2024/06/06 02:56
1.原型
  每创建一个函数,都有一个prototype属性,该属性指向一个对象,这个对象就是原型。
  选择一些属性和方法通过prototype挂在到原型上。每个new出来的实例,都有一个proto属性,该属性指向构造函数的原型对象,通过这个属性,
  让实例对象也能够放问原型对象上的方法。 因此,当所有的实例都能够proto放问到原型对象时,原型对象的方法与属性就变成共有的方法和属性。
        function Person(name,age){        this.name=name;        this.age=age;        }        Person.prototype.getName=function(){        return this.name;        }        var p1=new Person('zhangsan','11');        var p2=new Person('lisi','12')        console.log(p1.getName)        console.log(p1.getName===p2.getName);

可以发现:构造函数的prototype和实例对象的_proto_都指向原型,原型的constructor指向构造函数。

2.原型链


function foo() {}

foo是Function的实例。而Function的原型对象同时又是Object的实例,这样就构成了一条原型链。原型链和作用域链形式,都是单向查找的过程。
因此实例对象能够通过原型链,放问到处于原型链上对象的所有属性与方法。

function Parent(){};Parent.prototype.name='lisan';Parent.prototype.age='18';var son=new Parent();son.name="lisi";console.log(son.name);console.log(son.age);


3.作用域链
作用域的变量只能向上访问,变量访问到window对象即被终止,作用域链向下访问是不被允许的。

4.闭包
可以访问另一个函数的作用域中的变量, 创建闭包最常用的方式就是在一个函数中嵌套另一个函数,通过另一个函数访问这个函数的局部变量。
缺点:消耗内存,使用不当容易造成内存泄露。
作用:可以管理私有变量和方法,将变量封装在安全环境中,不能被外部随意修改,同时又可以通过制定函数接口来操作。
特性:1.函数嵌套函数 2.函数内部可以引用外部的参数和变量 3.参数和变量不会被垃圾回收机制回收

   var foo = ( function() {           var secret = 'secret';           // “闭包”内的函数可以访问 secret 变量,而 secret 变量对于外部却是隐藏的           return {               get_secret: function () {                   // 通过定义的接口来访问 secret                   return secret;               },               new_secret: function ( new_secret ) {                   // 通过定义的接口来修改 secret                   secret = new_secret;               }           };       } () );       foo.get_secret (); // 得到 'secret'       foo.secret; // Type error,访问不能       foo.new_secret ('a new secret'); // 通过函数接口,我们访问并修改了 secret 变量       foo.get_secret (); // 得到 'a new secret'



5、this的指向
1、作为普通函数调用(this指向全局window对象)
2、作为对象调用(this指向该对象)
3、构造器调用(this指向用new返回的这个对象)
4、call、apply、bing的调用(this指向第一个参数对象)


6、高阶函数
JavaScript的函数其实都指向某个变量。既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数称之为高阶函数。
特点1、函数作为参数传递 2、函数作为返回值输出


7、new操作符具体做了什么
1.创建一个新的对象
2.将构造函数的作用域赋给新对象(this指向当前新对象)
3.执行构造函数中的代码(为新对象添加属性)

4.返回新对象



8、bind apply call
共同点:都可以改变this的指向,第一个参数是this要指向的对象,也就是指定的上下文
 区别:call 传入的参数数量不固定,第二部分参数要一个一个传,用,隔开。
       apply 接收两个参数,第二个参数为数组
       bind返回一个改变上下文的函数副本,便于稍后调用,apply,call是立即调用。

function fruits() {}  fruits.prototype = {    color: "red",    say: function() {        console.log("My color is " + this.color);    }}  var apple = new fruits;apple.say();    //My color is red//但是如果我们有一个对象banana= {color : "yellow"} ,我们不想对它重新定义 say 方法,那么我们可以通过 call 或 apply 用 apple 的 say 方法:banana = {    color: "yellow"}apple.say.call(banana);     //My color is yellowapple.say.apply(banana);    //My color is yellow//所以,可以看出 call 和 apply 是为了动态改变 this 而出现的,当一个 object 没有某个方法(本栗子中banana没有say方法),但是其他的有(本栗子中apple有say方法),我们可以借助call或apply用其它对象的方法来操作。    //定义一个 log 方法,让它可以代理 console.log 方法,常见的解决方法是:function log(msg) {   console.log(msg);}log(1);    //1log(1,2);    //1  //当参数不确定时:function log(){  console.log.apply(this, arguments);};log(1);    //1log(1,2);    //1 2var foo = {    bar : 1,    eventBind: function(){        var _this = this;        $('.someClass').on('click',function(event) {            /* Act on the event */            console.log(_this.bar);     //1        });    }}  //由于 Javascript 特有的机制,上下文环境在 eventBind:function(){ } 过渡到 $('.someClass').on('click',function(event) { }) 发生了改变,上述使用变量保存 this 这些方式都是有用的,也没有什么问题。当然使用 bind() 可以更加优雅的解决这个问题:var foo = {    bar : 1,    eventBind: function(){        $('.someClass').on('click',function(event) {            /* Act on the event */            console.log(this.bar);      //1        }.bind(this));    }}      //apply、call、bind比较var obj = {    x: 81,};  var foo = {    getX: function() {        return this.x;    }}  console.log(foo.getX.bind(obj)());  //81console.log(foo.getX.call(obj));    //81console.log(foo.getX.apply(obj));   //81  //三个输出的都是81,但是注意看使用 bind() 方法的,他后面多了对括号。  //也就是说,区别是,当你希望改变上下文环境之后并非立即执行,而是回调执行的时候,使用 bind() 方法。而 apply/call 则会立即执行函数。

原创粉丝点击