第六周|第六周 JS 学习笔记

这周天气开始回暖,课上大家都很犯困,可能是讲的内容比较晦涩难懂吧
一、函数
1)模仿块级作用域

  • 自调用函数
  1. 写法
(function(){})() (function(){}())

  • 沙箱模式模仿块级作用域
function outputNumbers(count){ (function(){ for(var i=0; i< count; i++){ console.log(i) } })() console.log(i)// 报错 }

在外部环境中无法访问沙箱环境中的任何数据,但是由于在沙箱中this指向全局,故可以修改外部的数据
2)递归
  • 典型递归
function factorial(num){ if(num <= 1){ return 1 }else { return num * factorial(num -1) } }

  • 使用callee实现
function factorial(num){ if(num <= 1){ return 1 }else { return num*arguments.callee(num-1) } }

  • 解耦函数名,隔离
var factorial = (function f(num){ if(num <= 1){ return 1; }else { return num * f(num-1) } })

3)闭包
  • 引用外部数据
function foo(name){ return function(){ console.log(name) } }

** 导致数据被缓存,无法释放
  • 利用闭包解决引用问题
function createFunction(){ var result = new Array(); for(var i=0; i<10; i++){ result[i] = function (num){ return function(){ return num; // 引用num 导致num无法释放 } }(i) } return result; }

  • 闭包产生的this 指向问题
var name = 'The window'; var obj ={ name: 'my obj', getNameFunc: function(){ return function(){ return this.name } } } console.log(obj.getNameFunc()())// The window // 导致this指向全局的原因: 每个函数在被调用时都会自动取得两个特殊变量this和arguments , // 内部函数在搜索这两个变量的时候,只会搜索到其活动对象为止

4)私有变量
  • 模块模式
var singleton = function (){ var privateVariable = 10; function privateFunc(){ return false; } // 创建对象 var object = new CustomType(); // 特权,公有方法和属性 object.publicProperty = true; object.publicMehod = function(){ privateVariable++; return privateFunc() } return object; }()

此方法,内部的私有变量和方法得以保护,外界无法通过singleton变量访问
二、面向对象
1)属性类型
  • 数据属性
* Configurable 是否可配置 * Enumerable 是否可枚举 * Writable 是否可修改 * Value 属性的数据值

  • 修改属性的默认特性
var o ={}; Object.defineProperty(o,'name',{ value: '中国', writable: false }) o.name = '美国' console.log(o.name)

  • 访问器属性
var book ={ _year: 2001, edition: 1 }; Object.defineProperty(book, 'year',{ get: function(){ return this._year }, set: function(newVal){ if(newVal > this._year){ this._year = newVal; this.edition += newVal - 2001; } } }) book._year = 2002; console.log(book.edition) console.log(book._year)

调用 get 和 set 两个存取器方法 ,能够限制修改属性的值
  • 定义多个属性的特性
var o2 = {} Object.defineProperties(o2,{ _year: { writable:true, value: 2004 }, edition: { writable: true, value: 1 }, year: { get: function(){}, set: function(){} } })

  • 读取属性的特性
var descriptor = Object.getOwnPropertyDescriptor(book,"year")

2)创建对象 构造函数 + 原型模式
function Mode(name, age, job){ this.name = name; this.age = age; this.job = job; } Mode.prototype = { constructor: Mode, sayName: function(){ console.log(this.name) } } var mode = new Mode('Nick', 30, 'software')

  • in 操作符 判断是否是可访问的属性
var o5 = { name: '张三' } console.log("name" in o5)

  • for-in 遍历所有可访问的属性
function Animal(name){ this.name } Animal.prototype.size = 23; var animal = new Animal('狮子') animal.sex = '公' for(var prop in animal){ console.log(prop) }

  • Object.keys()
console.log(Object.keys(animal))

返回所有可枚举的实例属性的一个字符串数组, 不会遍历到原型上
  • Object.getOwnPropertyNams
console.log(Object.getOwnPropertyNames(Animal.prototype))

【第六周|第六周 JS 学习笔记】此方法用于获取所有实例的属性,不管是否可枚举
3)继承
  • 组合继承
    组合继承 首先会使用对象冒充的方式去继承父类构造函数中的属性,接着通过对子类的prototype.constructor设置进行构造器校正。
function SuperType(name){ this.name = name; this.colors = ['red','blue','green'] } SuperType.prototype.sayName = function(){ console.log(this.name) } function SubType(name,age){ //继承属性 SuperType.call(this, name); this.age =age; } // 继承方法 SubType.prototype = new SuperType() SubType.prototype.constructor = SubType; SubType.prototype.sayAge= function(){ console.log(this.age) }

  • 寄生组合式继承
function inheritPrototype(subType,superType){ var prototype = Object.create(superType.prototype); prototype.constructor = subType; subType.prototype = prototype; } function SuperType(name){ this.name = name; this.colors = ['red','blue','green'] } SuperType.prototype.sayName = function(){ console.log(this.name) } function SubType(name,age){ SuperType.call(this,name); this.age =age; } inheritPrototype(SubType,SuperType); var subtype = new SubType('张三', 23) subtype.sayName(); // 张三

    推荐阅读