构造函数
专门用来生成实例对象的函数,它是对象的模板。
构造函数有两个特点
- 函数内部使用了 this 关键字
- 生成对象的时候,必须使用 new 命令
var UserNumber = function (arguments) {
'use strict'
this.toString = '' + arguments
this.Method = 'Hello World'
}
var a = new UserNumber(null)
a.toString // 'null'
a.Method // 'Hello World'
let 士兵 = function (兵种,血量,攻击力) {
this.兵种 = 兵种,
this.血量 = 血量,
this.攻击力 = 攻击力
}
//prototype 中存士兵的共有属性
士兵.prototype = {
'移动速度': '10'//移动速度就是士兵的共有属性
}
//利用 士兵 这个构造函数创造一个兵王的 实例
let 兵王 = new 士兵('中国士兵',100000,100000)
// 兵种: "中国士兵", 血量: 100000, 攻击力: 100000
构造函数一般会和原型链以前应用。我们会把对象的共有属性添加到原型中
在new的过程成,会生成一个空对象,作为将要返回的对象。并将这个空对象赋值给函数内部的this。如果构造函数内部 reutrn 了一个对象,那么 new 命令就会返回 return 后面的对象。如果 return
后面有 this, 这个 this 是指向构造函数的
function Fn(){
this.name = '小明'
return {name: '小王'}
}
// return 了一个对象,所以 new 就会返回 return 后面的对象
let fn = new Fn()
fn.name // 小王
function Fn1(){
this.name = '小明'
return 1
}
fn = new Fn1()
fn.name // 小明
如果return中包含this,那么这个this会指向构造函数
function Fn(){
this.name = '小明'
return this
}
let fn = new Fn()
fn.name // 小明
function Fn1(){
this.name = '小明'
return {name: this.name}
}
fn = new Fn1()
fn.name // 小明
形参,实参
function fn(a,b){ // a,b就是形参
return a + b
}
fn(1,2) //1,2就是实参
实参可以是任何的数据类型
当一个函数需要传的参数很多时,可以吧参数包装一个成对象传给函数
function fn(options){
console.log('我是'+options.name+'我今年'+options.age+'我住在'+options.city)
}
fn({
name: '张三',
age: 18,
city: '北京'
})
//我是张三我今年18我住在北京
函数的声明方法
function和var类似,它是一种特殊的声明方式,所以function也会变量提升
- 具名函数
function fn(x,y) {return x + y}
fn.name //'fn'
- 匿名函数
var fn
fn = function (x,y) {return x + y}
fn.name //'fn'
- 将具名函数赋值给变量
//这种方法无法用fn来获取函数
var a = function fn(x,y) {return x + y}
fn.name //Uncaught ReferenceError: fn is not defined
a.name //'fn'
- window.Function函数
var fn = new Function ('x','y','return x+y')
fn.name //'anonymous'
- 箭头函数
var fn = (x,y) => {return x + y}
var fn = (x,y) => x + y
var fn = n => n*n
函数的调用方式
function fn(x,y) {return x + y}
fn(1,2)
fn.call(undefined,1,2)
声明函数后立即执行
(function(){
var parent = document.querySelector('#parent')
console.log(parent)
}).call()
!function(){
var parent = document.querySelector('#parent')
console.log(parent)
}.call()
this
函数都会接受一个隐藏的参数 this ,默认是window; 已方法的形式调用,this 就是调用这个方法对象
箭头函数不会改变
this,外面的this是什么内部的this就是什么call,bind,apply,可以改变this
function fn() {
console.log(this)
}
fn() //window
let obj = {
name: '张三',
age: 18,
fn: fn
}
obj.fn() // {name: "张三", age: 18, fn: ƒ}
function fn(x,y) {
console.log(this)
return x + y
}
fn.call(undefined,1,2)
//Window{postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, parent: Window,…}
//3
function fn(x,y) {
'use strict' //严格模式
console.log(this)
return x + y
}
fn.call(undefined,1,2)
//undefined
//3
function fn() {
console.log(this)
}
fn.call(1)
//Number {1}
function fn() {
'use strict'
console.log(this)
}
fn.call(1)
//1
arguments
数组的参数
function fn(x,y) {
console.log(arguments)
}
fn.call(undefined,1,2) //1和2 就是 arguments
//Arguments(2)[1, 2, callee: ƒ, Symbol(Symbol.iterator): ƒ]0: 11: 2callee: ƒ fn(x,y)length: 2Symbol(Symbol.iterator): ƒ values()__proto__: Object
//undefined
得到 arguments 长得很像一个数组,但是它的原型链中没有 Array.prototype
作用域
函数内部的代码有自己的影响区域
作用域可以自己定义
函数内的赋值不会影响到函数外的,作用域链可以往上查找
var a = 1
function fn() {
a = 2
console.log(a)
}
fn.call() //2
console.log(a) //1
上面的例子发现在函数内的赋值并不会对外部的 a 产生影响,这就是因为函数有作用域
var a = 1
function f1(){
alert(a)
var a = 2
}
f1.call() // undefined
var a = 1
function f1(){
var a = 2
f2.call()
}
function f2(){
console.log(a)
}
f1.call() // 1
闭包
如果一个函数,使用了它范围外的变量,那么(这个函数+这个变量)就是闭包
var a = 1
function fn() {
console.log(a)
}
总结
函数内部声明的变量因为函数作用域的原因,不能被外部访问到。如果想要它被外部访问到可以把这个变量变成全局变量(window)