JavaScript函数及其prototype

一、定义

函数可以通过声明定义,也可以是一个表达式。

(1)函数声明式:

分号是用来分隔可执行JavaScript语句,由于函数声明不是一个可执行语句,所以不以分号结束。

function a(){
  console.log('bbb');
}

(2)函数表达式:

函数表达式以分号结尾,因为它是一个执行语句。

var a = function(){
  console.log('aaa');
}

(3)声明式变体:

var a = function a(){
  console.log('bbb');
}

完全等价于 function b(){}

二、函数执行

JavaScript解析器将当前作用域内声明的所有变量和函数都会放到作用域的开始处,但是,只有变量的声明被提前到作用域的开始处了,而赋值操作被保留在原处。

示例1:

var a = function(){
  console.log('aaa');
}
function a(){
  console.log('bbb');
}
a();	//结果:aaa

示例2:

(function() {
  console.log(noSuchVariable);
})();
//报错,因为noSuchVariable变量根本没定义

</pre><pre name="code" class="javascript">(function() {
	console.log(declaredLater);		//"undefined"
	var declaredLater = "Now it's defined!";
	console.log(declaredLater);		//"Now it's defined!"
})();
//上面这段代码是正确的,没有任何问题。

示例3:

var a; 	        // 声明一个变量,标识符为a
function a() {} 	// 声明一个函数,标示符也为a
alert(typeof a);  	// function

function a() {}
var a;
alert(typeof a);  //function

function a() {}
var a = 1;
alert(typeof a);  //number

var a = 1;
function a() {}
alert(typeof a);  //number

总结:

变量的声明被提前到作用域顶部,赋值保留在原地;

声明式函数整个“被提前”;

函数表达式只有变量“被提前”了,函数没有“被提前”;

同名情况下,变量先“被提前”,函数再“再被提前”(即函数覆盖变量)

赋值会根据前后顺序进行覆盖!

三、函数是对象[typeof instanceof]

在 JavaScript 中使用 typeof 操作符判断函数类型将返回"function"。但JavaScript函数描述为一个对象更加准确。JavaScript函数有属性和方法。

(1)typeof区分对象和其他原始值

JavaScript的数据类型分为:原始类型(数字、字符串、布尔值、null、undefined)和对象类型。

typeof[任何类型]返回值(boolean、string、number、object、undefined)和 function

typeof 2;     //'number'
typeof '2';   //'string'
typeof true;  //'boolean'
typeof [];    //'object'
typeof null;  //'object'
typeof undefined; //'undefined'
var a = function(){}; typeof a; //'function'

对于所有内置可执行对象,typeof一律返回“function”

typeof new Number(2);     //'object'
typeof new String('2');   //'object'
typeof new Boolean(true); //'object'

(2)instanceof[对象 instanceof 类]判断一个对象是否为类的实例

[] instanceof Object; //true
2 instanceof Number; //false
new Number(2) instanceof Number; //true

示例:

var a = function(){};
var b = function(){};
a.prototype = new b();
new a() instanceof b; //true
new a() instanceof Object; //true

首先确定b.prototype,如果b.prototype在a对象的原型链中,返回true,否则返回false。

注意;所有对象都是Object的实例。

(3)扩展 Object.prototype.toString.call([]) === ‘[object Array]‘;

四、prototype

JavaScript 对象有两种不同的属性,一种是对象自身的属性,另外一种是继承于原型链上的属性。

JavaScript中,类的所有实例对象都从同一个原型对象上继承属性,因此,原型对象是类的核心。

(1)只有函数有prototype,对象没有

var b = {};
b.prototype.bbb='bbb';  //报错b.prototype为undefined

function b(){}
b.prototype.bbb='bbb';
console.log(b);            //结果:function b(){}
console.log(b.prototype);  //结果:b {bbb: "bbb"}
console.log(b.bbb);        //结果:undefined
console.log(new b().bbb);  //结果:bbb

(2)prototype是函数的内置属性(用于设置函数的原型),__proto__是对象的内置属性(用于设置对象的原型)。

PS:注意区分函数和对象

function test(){}
test.prototype;   		//结果:test {}
new test().prototype;   //结果:undefined,对象没有prototype
new test().__proto__;   //结果:test {}

function a(){
     this.v='vvv';
}
a.prototype; //a {}
new a.__proto__; //a {}
new a().__proto__ === a.prototype;  //true 实例对象的__proto__,指向函数的原型

(3)每个JavasScript函数都自动拥有一个prototype属性。这个属性的值是一个对象,这个对象包含唯一一个不可枚举属性constructor。constructor属性的值是一个函数对象。

function a(){
     this.v='vvv';
}
a.prototype.constructor === a; //true[物理地址一样]
a.prototype.constructor; //constructor属性指代这个类
a.prototype.constructor.__proto__ === a.__proto__ === Function.prototype; //true
Object.prototype.constructor.__proto__ === Object.__proto__ === Function.prototype; //true

PS:所有构造器、函数的__proto__都指向Function.prototype,它是一个空函数(Empty function)

(4)实例

示例1:

function a(){}
function b(){}
a.prototype = {aaa:'aaa'};
b.prototype = a.prototype;
var aa1 = new a();
var bb1 = new b();
//aa1.prototype.aaa='xxx';   //错误,对象没有原型
a.prototype.aaa = 'xxx';
console.log( aa1.aaa );    //xxx
console.log( bb1.aaa );    //xxx

补充:a===b; //false    a.prototype === b.prototype; //true

实例2:

function a(){}
function b(){ this.bbb='bbb'}
a.prototype = new b();  //相当于a.prototype = {bbb: "bbb"};
console.log(new a().bbb ); //结果:bbb

补充:a.prototype === b.prototype;  //false

五、实例方法&静态方法

(1)实例方法

function a(){}
a.prototype.count = 0;
var a1 = new a();
a1.count++;
var a2 = new a();
a2.count++;
a.prototype.count;  //0

PS:方法类似 a.prototype.method = function(){}

(2)静态方法

function a(){}
a.count = 0;
new a().count();  //undefined,只能使用a.count调用

PS:方法类似 a.method = function(){}

(3)当代码var p = new Person()执行时,new 做了如下几件事情:

A. 创建一个空白对象

B. 创建一个指向Person.prototype的指针

C. 将这个对象通过this关键字传递到构造函数中并执行构造函数

六、闭包

函数定义时的作用域链到函数执行时依然有效。

示例-典型闭包:

var scope = "global scope";
function checkScope(){
  var scope = "local scope";
  function f(){
    return scope;
  }
  return f();
}
checkScope(); //local scope

示例:更为常用的闭包

function counter(){
  var n=0;
  return{
    count:function(){
      return ++n;
    },
    reset:function(){
      n=0;
    }
  };
}
var c1 = new counter();
c1.count(); //1
var c2 = new counter();
c2.count(); //1
c1.reset(); //c1置为0,c2不受影响
c2.count(); //2

PS:实例对象互相不影响,单个实例对象内的方法,共享私有变量。

七、通过调用方法的形式来间接调用函数:apply&call

function a(){
  console.log(this.x+this.y);
}
a.call({x:100,y:100});  //200

function C(){
  this.m = function(){
    console.log(this.x+this.y);
  }
}
var c = new C();
c.m.call({x:100,y:100});  //200

call&apply第一个实参是要调用函数的母对象,会变为this的值。

函数.call(对象,参数1,参数2);

函数.apply(对象,[参数1,参数2]); //数组形式

补充:

function a(a,b,c,d){

//将伪数组转变为真数组

var args = [].slice.call(arguments);

}

八、函数中this

function a(){
  console.log(this);  //a {}
  function b(){
    console.log(this);  //window
  }
  b();
}
new a();

特别注意:函数内部函数this指向window

此问题在严格模式已被修改;在非严格模式中,可使用变量接收外部函数this供内部函数使用,如var that = this;

九、回调(函数当参数)

function a(callback){

callback();

}

a(function(){

console.log(‘aaa‘);

});

更加灵活,主页面只需为子页面提供对应接口,具体处理逻辑全部由子页面处理。

时间: 2024-10-27 19:48:17

JavaScript函数及其prototype的相关文章

JavaScript函数,作用域以及闭包

JavaScript函数,作用域以及闭包 1. 函数 (1). 函数定义:函数使用function关键字定义,它可以用在函数定义表达式或者函数声明定义. a. 函数的两种定义方式: * function functionName() {} * var functionName = function(){} b. 两种函数定义不同之处 1). 声明提前问题 函数声明语句   :声明与函数体一起提前 函数定义表达式 :声明提前,但是函数体不会提前 请看下面图示:绿色线上面实在js初始加载的时候,查看

javascript函数参数、返回值类型检查

实现带参数.返回值类型声明的js函数: 类型定义:window.Str = Type.Str = Type.define('STRING', Type.isStr);var Per = Type.define('PERSON', function(p){    return p && p.type === 'person' && p.name;}); 定义函数:var addStr = Str(function(a, b){  return a + b;}, Str, St

JavaScript中Object.prototype.toString方法的原理

在JavaScript中,想要判断某个对象值属于哪种内置类型,最靠谱的做法就是通过Object.prototype.toString方法. ? 1 2 var arr = []; console.log(Object.prototype.toString.call(arr)) //"[object Array]" 本文要讲的就是,toString方法是如何做到这一点的,原理是什么. ECMAScript 3 在ES3中,Object.prototype.toString方法的规范如下:

对于JavaScript对象的prototype和__proto__的理解

一.Object和Function的关系: 刚学JavaScript的时候,看书上说JavaScript中万物皆对象,而javascript中的其他对象都是从Object继承而来,包括内置对象.瞬间觉得Object碉堡了! 后来,又认识了Function,才知道原来Function才是隐藏在幕后的大BOSS,Object只不过是个大师兄. Object和Function都是JS自带的函数对象,Function比较牛逼点,因为它是Object的构造函数,而且Object的__proto__属性指向

Javascript对象的prototype

转帖: http://www.alloyteam.com/2015/10/prototype/?hmsr=toutiao.io&bsh_bid=928776428 最近恰好有人问起关于 javascript 中的 prototype 相关的问题.特此简单地整理了一下,比较基础,希望能让有类型问题的同学,可以用这篇文章提供参考. prototype 是通过调用构造函数而创建的对象实例的原型对象. 每一个新的函数,都会拥有一个 prototype 属性,这个属性指向函数的原型对象. 所有原型对象都有

理解javascript中的prototype

以前一直对javascript中的prototype不是很理解,今天在阅读了<javascript高级程序设计之后>终于理解了其中的prototype.来简单的总结一下从书中学习到的内容. 我们都知道在创建了一个function之后,这个function就具有了prototype这样的一个属性,利用这个prototype我们可以做很多的事情,其中我们经常用到的一点就是利用它来当做构造函数,因此,本文重要从function作为构造函数的角度来说明一下prototype. 其实javascript

JavaScript函数的调用模式有哪些?

函数是JavaScript 世界里的第一公民,换句话来说,就是我们如果可以精通 JavaScript 函数的使用,那么对JavaScript 的运用可以更游刃有余了.熟悉 JavaScript 的人应该都知道,同样的函数,以不同的方式调用的话,受影响最大的应该是  this  .下面我们来说说 JavaScript 函数的各种调用模式,希望对大家 学习javascript有所帮助. 一.普通函数的调用模式 所谓普通函数的调用模式,也是JavaScript 函数的最简单的一种调用模式,直接就是函数

深入浅出JavaScript函数 v 0.5

本文的观点是建立在<JavaScript权威指南 6th Ed> <JavaScript高级编程 3th Ed> <JavaScript精粹 2th Ed>之上, 笔者将尽所能将概念.原理叙述清楚,由于笔者水平有限,理解不当之处在所难免,请读者不吝交流. 目录 1 什么是函数? 2 函数就是对象! 3 函数字面量(函数表达式) 4 函数调用 4.1 方法调用模式 4.2 函数调用模式 4.3 构造器调用模式 4.4 间接调用模式 5 函数的参数与返回值 6 扩充类型的功

Javascript之深入浅出prototype

Javascript之深入浅出prototype 我们先来讲一个故事,一个大大的池塘,里面有很多鱼.这是属于我们大家的池塘所以里面的鱼我们都可以吃,但是我们也会从集市买一些鱼放在家里,那么放在家里的鱼肯定是属于我们私人的,外人是不会拥有的.那么在js里我们就把这个池塘称为原型对象,池塘里面我们所共享的鱼称为原型中的属性及方法,而我们自己的鱼称为构造函数中的属性及方法,我们是什么呢?对了,我们是对象的实例. 以上是为了让大家能够趣味性的对prototype有一个概念,接下来就通过代码具体总结一下p