一、三种创建对象的方式
// 字面量
var per1 ={
name: ' kkkk ',
age: ' 49 ',
eat: function () {
console.log( " 11 " )
}
}
// 系统构造函数
var per2 = new object();
per2.name = " jhdejg ";
per2.age =30;
per.eat = function () {
console.log( " 22 " )
}
// 自定义构造函数
function Person (name,age,sex) {
this.name = name;
this.age = age;
this.sex= sex;
this.eat = function() {
console.log( " 22 " )
}
}
var per = new Person( "zhenzi",33,"女" );
// new : 开辟空间存储对象,把this设置当前对象,设置属性和方法的值,把this对象返回
// 工厂模式
function gonghang(name,age,sex) {
var obj = new object();
obj .name = name;
obj .age = age;
obj .sex= sex;
obj .eat = function() {
console.log( " 22 " )
}
return obj;
}
var per = Person( "zhenzi2",33,"女" );
// 工厂模式和自定义构造函数的对比
/*
共同点:都是函数,都可以创建对象,都可以传入参数
不同点:
工厂模式:函数名是小写,有new,有返回值,new之后的对象是当前对象,直接调用函数就可以创建对象
自定义构造函数:函数名是首字母是大写,没有new,没有返回值,this是当前对象,通过new的方式来创建对象
*/
二、构造函数和实例对象的关系
function Person (name,age,sex) {
this.name = name;
this.age = age;
this.sex= sex;
this.eat = function() {
console.log( " 22 " )
}
}
var per = new Person( "zhenzi",33,"女" );
console.dir( per )是把这个对象的结构显示出来
// 判断这个对象是不是这种数据类型,下面代码打印出来是true
1: console.log( per.constructor == Person )
2: console.log( per instanceof Person )
总结:实例对象和构造函数之间的关系:
1:实例对象是通过构造函数来创建的,创建的过程叫做实例化
2:如何判断对象是不是这个数据类型?
1):通过构造器的方式,实例对象.构造器 == 构造器的名字
2)对象 instanceof 构造函数名字
尽量使用第二种方式来识别
三、原型
作用:数据共享,节省内存空间
function Person (name,age,sex) {
this.name = name;
this.age = age;
this.sex= sex;
}
// 通过原型添加方法
Person.prototype.eat = function() {
console.log( " 22 " )
}
var p1 = new Person( " 小明", 33 )
var p2 = new Person( " 小", 22 )
console.log( p1.eat === p2.eat ) // true
console.log( p1)
console.log(Person)
console.log( p1)
console.log(Person)打印出来结果如下
image.png
image.png
四、面向对象
初级:
function ChageStyle ( btnId,dvId,color ) {
this.btnobj = document.getElementById( btnId) ; // 对象
this.dvobj = document.getElementById( dvId) ; // 对象
this.color=color ;
}
// 数据共享来改变颜色
ChageStyle .prorotype.init = fuction () {
console.log( this ); // this就是实例对象
}
// 实例化对象
var cs = new ChageStyle (' btn ',' dv ', ' red');
cs.init();
// 进阶
function ChageStyle ( btnobj,dvobj ,json) {
this.btnobj = btnobj
this.dvobj = dvobj
this.json=json;
}
// 数据共享来改变颜色
ChageStyle .prorotype.init = fuction () {
var that = this;
this.btnobj .onclick = function() {
for( var k in that.json ){
that.dvobj.style[ k ] = that.json[ k ];
}
}
}
// 实例化对象
var json = {
" width":"500px";
" height":"500px";
" color":"red";
};
var cs = new ChageStyle (document.getElementById('btnid'),document.getElementById("idv"), json );
cs.init();
结论:
实例对象中有一个属性proto,也是对象,叫原型,不是标准的属性,浏览器使用的
构造函数中有一个属性prototype,也是对象,叫原型,是标准的属性,程序员使用的
实例对象使用的属性或者方法,先在实例中查找,找到了直接使用。找不到则去实例对象的proto指向的原型对象prototype中找,找到了则直接使用,找不到则报错
五、局部变量变成全局变量
// 函数自调用
(function(win){
// win是形参,window是实参
var num = 10;
win.num = num // 暴露到全局
})(window)
console.log(num) // 10
(function(win){
// win是形参,window是实参
function Person(){ }
Person.prototype.init= function(){
return Math.floor(Math.random()*5);
}
window.ss = new Person();
})(window)
console.log(ss.init())
六、原型继承
// 动物的构造函数
function Anomal(name,weight) {
this,name = name;
this.weight = weight;
}
// 动物的原型方法
Anomal.prototype.eat = funciton(){
console.log("天天吃");
}
// 狗的构造函数
function Dog(color){
this.color = color;
}
Dog.prototype = new Anomal("哮天犬","50k");
Dog.prototype.bitePerson = function(){
console.log("汪汪汪")
}
function ErHa(sex){
this.sex= sex;
}
ErHa.prototype = new Dog("黑白色");
ErHa.prototype.playHost = function(){
console.log("哈哈,好玩")
}
var ErHa = new ErHa("雄性");
ErHa.eat()
ErHa.bitePerson();
ErHa.playHost();
apply和call方法中如果没有传入参数,或者是传入null,那么调用该方法的函数对象中的this就是默认的window
apply (对象,【参数】);
call(对象,参数1,参数2,参数3.。。。)
函数名字:bind(对象,参数1,参数2,参数3.。。。),返回值是复制之后的这个函数
方法名字:bind(对象,参数1,参数2,参数3.。。。)返回值是复制之后的这个方法
apply可以改变this的指向
apply和call是调用的时候改变this指向,bind是赋值了一份的时候改变this指向,案例如下
function f1(x,y){
console.log((x+y)+":=========>"+this.age);
// this是下边的per
}
function Person(){
this.age = 1000;
}
Person.prototype.eat = function(){
console.log("这个是吃")
}
var per = new Person();
var ff = f1.bind( per ,10,20);
ff();
bind的应用
function ShowRandom(){
// 1-10的随机数,没有加1就是1-9
this.number = parseInt(Math.random()*10+1)
}
// 添加原型方法
ShowRandom.prototype.show1 = function(){
// 改变了定时器的this指向,本来应该是window,现在是实例对象
window.setInterval(this.show2.bind(this),1000)
}
// 添加原型的方法
ShowRandom.prototype.show2 = function(){
// 显示随机数
console.log(this.number)
}
// 实例对象
var per = new ShowRandom()
per .show2();
七、函数作为参数
function f1(fn){
fn();// fn当成一个函数来使用,fn是传参,最后当做函数使用,函数是可以作为参数使用
}
// 匿名函数
f1(function(){
console.log("我是匿名函数")
})
// 命名函数
function f2(){
console.log("f2的函数")
}
f1(f2)
// 函数作为参数的时候,如果是命名函数,那么只传命名函数的名字,没有括号
image.png
// 定时器里调用
function f1(fn){
setInterval(function(){
console.log("定时器开始");
fn();
console.log("定时器结束");
})
}
// f1传了一个函数作为参数来调用
f1(function(){
console.log("好困啊,好累啊啦啦啦");
})
函数作为返回值
function f1(){
console.log("f1函数开始")
return function(){
console.log("我是函数,但是此时是作为返回值使用的");
}
}
var ff = f1();
ff();
image.png
七、浅拷贝和深拷贝
浅拷贝
深拷贝
网友评论