js学习之函数
一、JS声明函数的三种方式:
1、// 函数声明(function declaration) 赋值发生在代码解析阶段
function h() {
// h
}
2、// 函数表达式(function expression) 赋值发生在代码运行阶段, :函数表达式需要在语句的结尾加上分号,表示语句结束。而声明式定义函数在结尾的大括号后面不用加分号:
var h = function() {
// h
}
3、使用Function构造函数 ,不建议这种方式
var add2=new Function();调用 :add2()
二、函数特点
1、函数提升优先级比变量提升要高,且不会被变量声明覆盖,但是会被变量赋值覆盖。
2、在函数中,参数是局部变量
3、在函数中 return 语句可以让函数提前返回。return 被执行时,函数会立即返回。
一个函数总会返回一个值,如果没有指定这个值,它就会返回 undefined。
三、立即执行的函数的几种写法
1、
(function () {
alert(1);
})();
2、
(function () {
alert(2);
}());
3、
! function () {
alert(3);
}();
四、函数中this的指向
var aa = {
name:"xz",
age:20,
run:function(){
console.log(this);
}
}
aa.run(); //this指向aa对象
注释:当一个函数被保存为对象的一个属性时,就称它为方法。当方法被调用时,this 被绑定到这个对象。
function bb(){
console.log(this);
}
bb(); //this指向window对象
构造函数调用模式 :new 函数名();
this:指向new出来的对象
五、函数参数 arguments
当函数被调用时,会有一个 arguments 数组。arguments 不是一个真正的数组,它只是一个类数组的对象,它拥有 length 属性,但没有数组的相关方法。
六、构造函数
构造函数的特点有:
a:构造函数的函数名首字母必须大写。
b:内部使用this对象,来指向将要生成的对象实例。
c:使用new操作符来调用构造函数,并返回对象实例。
eg:
function Person(){
this.name = 'keith';
}
var boy = new Person();
console.log(boy.name); //'keith'
缺点:
所有的实例对象都可以继承构造函数中的属性和方法。但是,同一个对象实例之间,无法共享属性。
function Person(name,height){
this.name=name;
this.height=height;
this.hobby=function(){
return 'watching movies';
}
}
var boy=new Person('keith',180);
var girl=new Person('rascal',153);
console.log(boy.name); //'keith'
console.log(girl.name); //'rascal'
console.log(boy.hobby===girl.hobby); //false
一个构造函数Person生成了两个对象实例boy和girl,并且有两个属性和一个方法。但是,它们的hobby方法是不一样的。也就是说,每当你使用new来调用构造函数放回一个对象实例的时候,都会创建一个hobby方法。这既没有必要,又浪费资源,因为所有hobby方法都是童颜的行为,完全可以被两个对象实例共享。
所以,构造函数的缺点就是:同一个构造函数的对象实例之间无法共享属性或方法。
prototype属性的作用:为了解决构造函数的对象实例之间无法共享属性的缺点,js提供了prototype属性。
js中每个数据类型都是对象(除了null和undefined),而每个对象都继承自另外一个对象,后者称为“原型”(prototype)对象,只有null除外,它没有自己的原型对象。
原型对象上的所有属性和方法,都会被对象实例所共享。
通过构造函数生成对象实例时,会将对象实例的原型指向构造函数的prototype属性。每一个构造函数都有一个prototype属性,这个属性就是对象实例的原型对象。
a:原型对象的作用,就是定义所有对象实例所共享的属性和方法。
b:prototype,对于构造函数来说,它是一个属性;对于对象实例来说,它是一个原型对象。
不是所有的对象都拥有prototype这一属性,只有函数有
prototype _proto_ constructor的区别?
1、我们需要牢记两点:
①__proto__和constructor属性是对象所独有的;
② prototype属性是函数所独有的,因为函数也是一种对象,所以函数也拥有__proto__和constructor属性。
2、__proto__属性的作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的__proto__属性所指向的那个对象(父对象)里找,一直找,直到__proto__属性的终点null,再往上找就相当于在null上取值,会报错。通过__proto__属性将对象连接起来的这条链路即我们所谓的原型链。
3、prototype属性的作用就是让该函数所实例化的对象们都可以找到公用的属性和方法,即f1.__proto__ === Foo.prototype。
4、constructor属性的含义就是指向该对象的构造函数,所有函数(此时看成对象了)最终的构造函数都指向Function。
console.log(aa.prototype) //一个对象
console.log(aa.__proto__)
console.log(aa.constructor) ////指向该对象的构造函数
console.log(aa.__proto__.constructor) ////指向该对象的构造函数
console.log(aa.__proto__.constructor === aa.constructor) //true
console.log(test.prototype) // undefind 对象没有prototype,prototype是函数所独有的
console.log(test.__proto__) //一个对象
console.log(test.constructor) //指向该对象的构造函数
console.log(test.__proto__.constructor) //指向该对象的构造函数
console.log(test.__proto__.constructor === test.constructor) //true
function Person(name, gender) { // 这个就是原型,也是一个构造函数,首字母大写
this.name = name;
this.gender = gender;
}
Person.prototype.eat = "哇,贼好吃."; // 在prototype写的方法,继承他的都能使用到
var person1 = new Person("MIse", "male"); // 这个就是 对象实例 他的原型就是 Person 这个构造函数
console.log(Person.prototype === person1.__proto__); //构造函数的prototype原型 和 构造函数实例化出来的对象的__proto__相等
console.log(person1.constructor === Person.prototype.constructor); //true
一个函数都包含一个prototype(对象)属性,这个属性指向的是一个对象的引用;
每一个prototype对象里面都有一个constructor,这个constructor指向的是构造函数本身
构造函数的Person.prototype.constructor属性是构造函数 指向的是构造函数本身
构造函数实例化出来的对象的 person1.constructor 指向的是构造函数本身