JavaScript中函数也是一个对象,那么对象中就可以有属性和方法,他有一些默认的属性
...
语法不会被算在内)PS: 箭头函数不绑定 Arguments 对象
arguments 转为数组对象常见方法
普通的方法 就是将内容一个一个迭代到新数组了
let newArray = []
// arguments
function foo1(m, n) {
for (var arg of arguments) {
newArray.push(arg)
}
// arguments类似数组的对象(它可以通过索引来获得对象)
console.log(newArray)
}
foo1(1, 2)
ES6 中的方法
...
的方式来复制 // 方法2
var newArray1 = Array.from(arguments)
// 方法3
var newArray = [...arguments]
rset
如果最后一个参数是 … 为前缀的,那么它会将剩余的参数放到该参数中,并且作为一个数组
function foo1(m, n, ...arg)
副作用: 执行函数时,除了返回函数值之外,还对调用函数产生了附加的影响,比如修改了全局变量,修改参数或者改变外部的存储
纯函数的理解
var names = ["abc", "nba", "nbc", "cbd"]
var newNames = names.slice(0, 2)
var newNames1 = names.splice(0, 2)
console.log(newNames);
console.log(newNames1);
函数式编程重要概念,他是一个作用于函数的高阶技术,在其他的编程语言也有使用
只传递函数部分参数来调用,让它返回一个函数去处理剩余的参数这个过程就被成为柯里化
// 普通的函数
function foo(x, y, z) {
console.log(x + y + z);
}
foo(10, 20, 30)
// 柯里化的结果
function kelifoo(x) {
return function (y) {
return function (z) {
console.log(x + y + z);
}
}
}
kelifoo(10)(20)(30)
//箭头函数写法
var foo2 = x => y => z => { console.log(x + y + z) }
// 需要转化的例子
function sum(num1, num2) {
console.log(num1 + num2);
return num1 + num2
}
// 自动柯里化函数
function hyCurrying(fn) {
// 1 继续返回一个新的函数 继续接受函数
// 2 直接执行 fn 函数
function curryFun(...args) {
if (args.length >= fn.length) {
// 执行第二种操作
return fn.apply(this, args)
} else {
return function (...newArgs) {
return curryFun.apply(this, args.concat(newArgs))
}
}
}
return curryFun
}
// 对其他函数柯里化
var sumCurry = hyCurrying(sum)
sumCurry(10)(5)
sumCurry(10, 5)
柯里化函数只有在某些特殊的场景才需要使用。他得性能并不高也可能引起闭包的内存泄漏所以使用的时候需要注意。
当我们需要嵌套调用两个函数的时候,为了方便复用,我们可以写一个组合函数
var sum = pow(double(12))
我们可以编写一个通用的组合函数来让我们使用组合函数更加的便捷,其实思路就是很简单的将函数放入数组判断边界顺序执行
function sum(num) {
return num * 2
}
function pow(num) {
return num ** 2
}
function composeFn(...fns) {
// 边界判断
var length = fns.length
if (length < 0) {
return
}
for (let i = 0; i < length; i++) {
var fn = fns[i]
if (typeof fn != "function") {
throw new Error(`index postion ${i} must be function`)
}
}
//轮流执行函数 返回结果对象
return function (...args) {
var result = fns[0].apply(this, args)
for (let i = 1; i < length; i++) {
var fn = fns[i]
result = fn.apply(this, [result])
}
return result
}
}
var newfn = composeFn(sum, pow)
console.log(newfn(5)); //100
with
语句 扩展一个语句的作用域链,不推荐使用有兼容性问题
eval
允许执行一个代码字符串。他是一个特殊函数可以将传入的字符串当作js代码执行
js的局限性 :
ES5标准中提出了严格模式的概念,以更加严格的方式对代码进行检测和执行
只需要在代码的开头或者函数的开头 加入use strict
就可以开启严格模式
我们的属性一般定义在对象的内部或者直接添加到对象内部,但是这种方式我们就不能对属性进行一些限制,比如这个属性是否是可以通过delete删除,是否可以for-in遍历的时候被遍历出来等等
PS: 一个属性进行比较精准的操作控制,就可以使用属性描述符。
这个方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象
Object.defineProperty()
分为两类:
Configurable
:表示属性是否可以通过delete删除属性,是否可以修改它的特性
Enumerable
:表示属性是否可以通过for-in或者Object.keys()返回该属性;
Writable
:表示是否可以修改属性的值;
value
:属性的value值,读取属性时会返回该值,修改属性时,会对其进行修改
使用案例
var obj = {
name: "whit",
age: 12
}
Object.defineProperty(obj, "name", {
configurable: false,
enumerable: false,
writable: false,
value: "1234"
})
Configurable&Enumerable
也是存取属性描述符
get
:获取属性时会执行的函数。默认为undefined
set
:设置属性时会执行的函数。默认为undefined
同时定义多个属性
// 多个属性调用
Object.defineProperties(obj, {
name: {
configurable: false,
enumerable: false
},
age: {
enumerable: false,
writable: false,
}
})
获取对象的属性描述符:
禁止对象扩展新属性:preventExtensions
密封对象,不允许配置和删除属性:seal
冻结对象,不允许修改现有属性: freeze
代码案例
// 阻止对象的拓展
Object.preventExtensions(obj)
obj.address = 12
//密封对象 不能进行配置
Object.seal(obj)
delete obj.name
// 冻结对象
Object.freeze(obj)
obj.name = "ske"