##### 循环对象自身的属性
function Foo(name, age){
this.name = name
}
Foo.prototype.alertName = function(){
alert(this.name)
}
var f = new Foo('zhangsan');
f.printName = function(){
console.log(this.name);
}
var item
for(item in f){
//高级浏览器已经在for in中屏蔽了来自原型的属性
//但是这里建议大家还是加上这个判断,保证程序的健壮性
if(f.hasOwnProperty(item)){
console.log(item);
}
}
//构造函数
function Foo(name, age){
this.name = name
}
Foo.prototype.alertName = function(){
alert(this.name)
}
var f = new Foo('zhangsan');
f.printName = function(){
console.log(this.name);
}
f.printName()
f.alertName()
f.toString() //要去f.__proto__.__proto__({__defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, __lookupSetter__: ƒ, …})中查找
instanceof 用于判断引用类型属于哪个构造函数的方法
f instanceof Foo //true f的__proto__一层一层往上,能否对应到Foo.prototype
f instanceof Object //true
如何准确判断一个变量是数组变量
var arr = []
arr instanceof Array // true
typeof arr //object typeof是无法判断是否是数组的
一个原型链继承的例子
function Animal(){
this.eat = function () {
console.log('animal eat')
}
}
function Dog(){
this.bark = function () {
console.log('dog bark');
}
}
Dog.prototype = new Animal()
var hashiqi = new Dog();
描述new一个对象的过程
- 创建一个新对象
- this指向这个新对象
- 执行代码,即对this赋值
- 返回this
function Foo(name, age){
this.name = name;
this.age = age;
this.class = 'class-1'
}
var f = new Foo('zhangsan', 20)
zepto(或其他框架)源码中如何使用原型链
- 阅读源码是高效提高技能的方式
- 但不能“埋头苦钻”有技巧在其中
- 慕课网搜索“zepto设计和源码分析”
原型例子
function Elem(id){
this.elem = document.getElementById(id);
}
Elem.prototype.html = function(val){
var elem = = this.elem
if(val){
elem.innerHTML = val
return this
} else {
return elem.innerHTML
}
}
Elem.prototype.on = function(type, fn){
var elem = this.elem
elem.addEventListener(type, fn)
return this;
}
var div1 = new Elem('div1');
//div1.html('<p>111</p>');
div1.html('<p>111</p>').on('click', function(){
alert('clicked');
}).html('<p>222/p>');
example
function Foo(name, age){
this.name = name;
this.age = age;
this.class = 'class-1'
return {x: 10}
}
var f = new Foo('zhangsan', 20)
f//{x: 10}
this
//this要在执行时才能确认值,定义时无法确认
var a = {
name: 'A',
fn: function(){
console.log(this.name);
}
}
a.fn(); //this === a
a.fn.call({name: 'B'}); //this === {name: 'B'}
var fn1 = a.fn;
fn1(); //this === window
- 作为构造函数执行
- 作为对象属性执行
- 作为普通函数执行
- call apply bind
function Foo(name){
this.name = name;
}
var f = new Foo('zhangsan');
var obj = {
name: 'A',
printName: function(){
console.log(this.name);
}
}
obj.printName();
function fn() {
console.log(this)
}
fn()
function fn1(name){
alert(name);
console.log(this);
}
fn1.call({x:100},'zhangsan',20)//Object{x:100}
fn1.call({x:100},['zhangsan',20])
var fn2 = function(name){
alert(name);
console.log(this);
}.band({y:200})
fn2('zhangsan', 20)
只关心在哪里定义 不关心声明
var a = 100
function F1(){
var b = 200
function F2(){
var c = 300
console.log(a)
console.log(b)
console.log(c)
}
F2()
}
F1()
闭包
function F1() {
var a = 100
return function (){
console.log(a); //自由变量,父作用域寻找
}
}
var f1 = F1();
var a = 200
f1()
function F1(){
var a = 100
return function () {
console.log(a)
}
}
var f1 = F1()
function F2(fn){
var a = 200
fn()
}
F2(f1) //100
创建10个a标签 点击的时候弹出对应的序号
//错误
var i, a
for(i = 0; i < 10; i++){
a = document.createElement('a')
a.innerHTML = i + '<br>'
a.addEventListener('click', function(e){
e.preventDefault()
alert(i)
})
document.body.appendChild(a)
}
//正确
var i
for(i = 0; i < 10; i++){
(function(i){
a = document.createElement('a')
a.innerHTML = i + '<br>'
a.addEventListener('click', function(e){
e.preventDefault()
alert(i)
})
document.body.appendChild(a)
})(i)
}
实际开发中闭包的应用
//闭包实际应用中主要用于封装变量,收敛权限
function isFirstLoad(){
var _list = []
return function (id){
if(_list.indexOf(id)>=0){
return false
} else {
_list.push(id)
return true
}
}
}
var firstLoad = isFirstLoad()
firstLoad(10);//true
firstLoad(10);//false
firstLoad(20);//true