JS之函数

function add(x,y){        //函数,声明提升,可以在函数定义之前调用
    return x+y
}

var add = function (x,y){ //函数表达式,不会提升声明
    return x+y
}

var sum1 = function _sum(x){ //函数表达式不省略名字,也只能在函数内部使用
    if (x==1)               // if后不能加分号
    return 1;
    return x+_sum(x-1);
}
// console.log(sum(5))

const counter = function (){
    let c = 0
    return function (){
        return ++c
    }
}
c = counter()

arr = new Array(1,2,3,4,5)
var map = function map(arr,fn){
    let newarry = []
    for (i in arr)
        newarry[i] = fn(arr[i])
    return newarry
}


// console.log(map(arr,function(x) {return ++x}))//匿名函数
// console.log(map(arr,x=>++x)) //箭头函数,就是匿名函数,更加简洁

var map = function * (arr,fn){
    for(i in arr)
        yield fn(arr[i])

}
let newarr = map(arr,x=>++x)
/*
箭头函数:如果一个函数没有参数使用();
如果只有一个参数,可以省略小括号
多个参数不能省略小括号,且使用逗号间隔
箭头函数返回值:如果函数体部分有多行,就需要使用{},如果有返回值使用return
如果只有一行语句,可以同时省略大括号和return,有return必有{}
*/


const sum = function (...args){ //[1,2,3]
    let result = 0
    console.log(arguments) //所有的参数,包括位置参数
    for (let x in args){  //[[1,2,3]]
        // console.log(args[x],'~~~~~~~~~`')
        result += args[x]
    }
    return result
}
// console.log(sum(...[1,2,3,4,5]))
// console.log(100+[1,2,3,4]) //1001,2,3,4

const rvalue = (x,y) => {return x,y}
console.log(rvalue(5,6))
/*
表达式的值
赋值表达式的值:等号右边的值
逗号表达式的值:最后一个表达式的值
*/

1.1es6之前的类定义

定义一个函数(构造器对象)函数首字母大写
使用this定义属性
使用new和构造器创建一个对象
本质还是一个function //[Function: Point]
function Point(x,y){  //Es6之前
    this.x = x
    this.y = y
    this.show = ()=>console.log(this.x,this.y)
    
}
console.log(Point)
p1 = new Point(3,4)
console.log(p1)

function Point3d(x,y,z){
    Point.call(this,x,y)  //继承
    this.z = z
    console.log('this is Poind3d')
}
p2 = new Point3d(1,2,3)
console.log(p2)
p2.show()
注意:如果不使用new关键字,就是一次普通的函数调用,this不代表实例

 1.2 es6中class的定义

1.从es6开始,新提供了class关键字,是的创建对象更加简单,清晰
2.类定义使用class关键字,创建的本质还是函数,是一个特殊的哈数
3.一个类只能拥有一个constructor的构造器方法,如果没有显示的定义一个构造方法,则会添加一个默认的构造方法
4.继承使用extends关键字
5.一个构造器可以使用super关键字来调用一个父类的构造函数
6.类没有私有属性 

1.2.1 类的继承从父类全部继承

class Poing{
    constructor(x,y){
        this.x = x
        this.y = y
    }
    show()
    {   console.log(this) //实例p1
        console.log(this,this.x,this.y)
    }
}

p1 = new Poing(4,5)
console.log(p1)

class Poing3d  extends Poing{  //继承
    constructor(x,y,z){
        super(x,y)
        this.z = z 
    }
}
p2 = new Poing3d(7,8,9)
console.log(p2)
p2.show()

1.2.2 es6静态属性

class Poing{
    constructor(x,y){
        this.x = x
        this.y = y
    }
    show()
    {   console.log(this) //实例p1
        console.log(this,this.x,this.y)
    }
}

p1 = new Poing(4,5)
console.log(p1)

class Poing3d  extends Poing{  //继承
    constructor(x,y,z){
        super(x,y)
        this.z = z 
    }
    static set(){
        console.log('set')
    }
}
p2 = new Poing3d(7,8,9)
console.log(p2)
Poing3d.set()
p2.constructor.set() //实例只能通过这种方式访问静态属性

 2.1   this出现的问题整理与总结

c++。java是静态编译型语言,this是编译期间绑定,js是动态语言,运行期绑定
var school = {
    name:'python',
    getNameFunc:function(){
        console.log(this.name)
        console.log(this)
        return function (){
            console.log(this === global)
            return this.name
        }
    }
}
函数执行期间会开启新的上下文环境executioncontext,创建this属性,但是this是什么就要看函数怎么调用
1.myfunction(1,2,3)普通函数的调用方式,this指向全局对象,全局对象是nodejs的global或者浏览器的windows
2.myobject.myfunction(1,2,3)对象的调用方式,this指向包含该方法的对象
3.call和apply方法调用,需要看第一个参数是谁

2.1.1  this的显示传入

var school = {
    name:'python',
    getNameFunc:function(){
        console.log(this.name)
        console.log(this)
        return function (that){  //普通函数这块传入一个参数
            console.log(that === global)
            return that.name
        }
    }
}

console.log(school.getNameFunc()(school))
es3
apply.call方法都是函数对象的方法,第一个参数都是传入对象引入的 apply传入其他参数需要使用数组 call传入其他参数需要使用可变参数收集
var school = {
    name:'python',
    getNameFunc:function(){
        console.log(this.name)
        console.log(this)
        return function (){  //普通函数这块传入一个参数
            console.log(this === global)
            return this.name
        }
    }
}

console.log(school.getNameFunc().apply(school))
console.log(school.getNameFunc().call(school))

  2.1.2 bind es5,最常用的方式解决this问题

var school = {
    name:'python',
    getNameFunc:function(x,y){
        console.log(1,this)
        console.log(2,this.x,this.y)
        return function(){
            console.log(3,this === global)
            return this.name
        }
    }
}

// console.log(school.getNameFunc().bind(school)) //错误用法
var func = school.getNameFunc() //等同于上条调用
var boundfunc = func.bind(school) //bind返回i虚拟的函数,先为函数绑定this,调用时直接用
console.log(boundfunc())

 2.1.3  箭头函数解决this问题 es6新技术,不需要兼容this问题

var school = {
    name:'python',
    getNameFunc:function(x,y){
        console.log(1,this)
        console.log(2,this.x,this.y)
        return ()=>{
            console.log(3,this === global)
            return this.name
        }
    }
}

// console.log(school.getNameFunc().bind(school)) //错误用法
var func = school.getNameFunc() //等同于上条调用
var boundfunc = func.bind(school) //bind返回i虚拟的函数,先为函数绑定this,调用时直接用
console.log(boundfunc())

 3.1高阶对象MIXIN模式

/*
四种类的定义以及转换
*/
class A{}
const B = class {
    constructor(x){
        console.log(x)
    }
}
const C = class extends B{}


const D = Sup => class extends Sup{}//用一个函数来返回类的定义
cls = D(B)  //返回类定义
d = new cls(300)

 代码改造前后

class Serialization {
    constructor(){
        console.log('serialization constructor')
        if (typeof this.stringify!=='function'){
            throw new ReferenceError('show define stringify')
        }
    }
}


class Point extends Serialization{
    constructor(x,y){
        console.log('Point constructor')
        super()
        this.x = x
        this.y = y
    }
    stringify(){
        console.log(`Point <${this.x}:${this.y}>`)
    }
}


class Point3D extends Point {
    constructor(x,y,z){
        super(x,y)
        this.z = z
    }

}
p = new Point(2,3)
pd = new Point3D(5,6)
console.log('~~~~~~~~~~~~~~~~~~~~')
p.stringify()
pd.stringify()

 改造后

var serialization = Sup =>class extends Sup {
    constructor(...args){
        console.log('serialization constructor')
        super(...args)
        if (typeof this.stringify!=='function'){
            throw new ReferenceError('show define stringify')
        }
    }
}


class Point  {
    constructor(x,y){
        console.log('Point constructor')
        this.x = x
        this.y = y
    }
    stringify(){
        console.log(`Point <${this.x}:${this.y}>`)
    }
}


class Point3D extends serialization(Point) {
    constructor(x,y,z){
        super(x,y)
        this.z = z
    }

}
pd = new Point3D(5,6,6)
console.log(pd)

 js foreach 

var metadata ={
    title:'python',
    translations:[
        {
            locale:'de',
            url:{}
        }
    ]
}
console.log(Object.keys(metadata))
console.log(Object.values(metadata))
console.log(Object.entries(metadata))
var copy = Object.assign({},metadata,{school:"mage"},{url:null})
console.log(copy)



const arr = [1,2,3,4,5]
newarr = []
arr.forEach(
    function(x){
        newarr.push(x)
    }
)
console.log(newarr)

export default

使用export default时,对应的import语句不需要使用大括号;不使用export default时,对应的import语句需要使用大括号。

export default命令用于指定模块的默认输出。显然,一个模块只能有一个默认输出,因此export default命令只能使用一次。import命令后面才不用加大括号,因为只可能对应一个方法。

本质上,export default就是输出一个叫做default的变量或方法,然后系统允许你为它取任意名字
本文为原创文章,转载请标明出处
原文地址:https://www.cnblogs.com/harden13/p/9262957.html