2018-11-22 面向对象3

2018-11-22  本文已影响0人  满天繁星_28c5

JavaScript的面向对象是基于constructor(构造函数)与prototype(原型链)的。

1.构造函数:constructor

构造函数就是一个函数。和普通函数有一些区别:

2.原型:prototype

原型是一个对象,称为原型对象。
构造函数创建实例对象,构造函数具有原型,实例对象也具有原型。实例对象的原型指向构造函数的原型。这就是原型链。

3.原型链:
4.proto:每一个实例对象都具有的私有属性。指向自己的原型。

proto属性(前后各两个下划线),用来读取或设置当前对象的prototype对象。目前,所有浏览器(包括 IE11)都部署了这个属性。
eg:1__protp___
效果如下:

22.proto.jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>

</body>
<script>
let a = new Array();
console.log(a);

function A(){
    this.a = '1';
}
let b = new A();
console.log(b.__proto__)
console.log(A)
</script>
</html>

constructor: 构造器。指向自己的构造函数。

5.new :

创建对象实例。
防止漏掉new造成错误:
在构造函数内部使用严格模式。
使用instanceof在内部判断。判断是否为当前对象的实例。
使用new.target 在内部判断,new.target指向自己的构造函数。
eg:2new
效果如下:


22.new1.jpg 22.new1.1.jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>

</body>
<script>
ll = 'lala';
function A(name){
    console.log(this);      //此处的this指代的是全局作用域window
    this.ll = name;
    function ss(){
        alert(this.ll);
    }
}
A.prototype.say  = function(){
    alert(this.ll);
}
/*
let a = new A ('zhangsan');
a.say();    //页面弹出“zhangsan”的字样打印A{}的数组
*/
let a = A('lili');
console.log(ll)     //页面打印window的全局作用域 、 lili
</script>
</html>

eg:3new
效果如下:


22.new2.jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>

</body>
<script>
function A (name){
    'use strict';  //严格模式
    this.name = name;
}

let a = new A('lisi');

//递归
function  B(name){
    // this指向新创建的实例
    if(!(this instanceof B)){
        return new B(name);
    }
    this.name = name;
}
let b = new B('lili');
console.log(b.name);
let bb = B ('sisi');
console.log(bb.name);

//new.target指向自己的构造函数
function V (name){
    if(!(new.target == V)){
        throw new Error('这个对象必须使用new来创建对象');
    }
    this.name = name;
}
let v  = new V('kk');
let vv = V('kk');
</script>
</html>
6.new的深入操作:

1.创建一个空对象,作为将要返回的对象实例。
2.将这个空对象的原型,指向构造函数的prototype属性。
3.将这个空对象赋值给函数内部的this关键字。
4.开始执行构造函数内部的代码。
5.将对象实例返回
eg:4new
效果如下:


22.new3.jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>

</body>
<script>
function A(name){
    this.name = name;
    return  123;    //简单数据类型
}
let a = new A('123');
console.log(a);     //打印出的是A数组里面的内容

function B(name){
    this.name = name;
    return this;
}
let b = new B('123645');
console.log(b);     //打印出的是B数组里面的内容


function C(name){
        this.name = name;
        return {
            name:'zhangsan'
        };
}
let c = new C('1689156');
console.log(c);    //打印出的是C数组里面的内容
</script>
</html>
7.构造函数里面的return语句:

如果return的是普通数据类型。那么相当于没写。
如果返回的是this,那么返回的与本身返回的是一样的。
如果返回的是一个其他对象。那么结果返回的就是这个对象。所以在构造函数内部返回对象要小心。

8.任何一个函数都可以使用new。返回值都是一个对象。

如果这个函数是一个构造函数的话,返回的是这个函数的实例。
如果函数是一个普通函数,那么返回的是一个空的对象。

9.Object对象,是所有JS对象的基础。

Object 的原型指向null。一切对象的基础是null,null也叫空。
eg: 5 Object
效果如下:


22.5Object.jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>

</body>
<script>
console.log(Object.prototype.__proto__);    //打印得null说明打印出的是对象原型是空
</script>
</html>
9.(1)Object.create();

有的时候我们拿不到对象的构造函数。可以根据这个对象的某一个实例去创建一个对象。
eg:6create
效果如下:


22.6create.jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>

</body>
<script>
function A(name){
    this.name = name;
}
let a = new A('LILI');

let b = Object.create(a);       //有的时候我们拿不到对象的构造函数。可以根据这个对象的某一个实例去创建一个对象。

console.log(b);     //A name: "zhangsan"__proto__: A  此处获取的是b.name的命名'zhangsan'

b.name = 'zhangsan';
console.log(a.name);    //LILI 此处获取的是a中为A创建的一个实例'LILI'
</script>
</html>

对于对象来说,每一个属性 其实都有四个描述。
value 值
enumerable 枚举 遍历 for in
configurable 修改
writable 删除
后面三个默认值都是true。
eg:7create
效果如下:


22.7create.jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>

</body>
<script>
let obj = new Object();
//添加属性
obj.p1 = 'lili';
obj.p2 = 16;

let obj2 = Object.create(obj,{  //有的时候我们拿不到对象的构造函数。可以根据这个对象的某一个实例去创建一个对象。(后面三个默认值都是true。)
    /*value:值
    enumerable:true,
    configurable:true,
    writable:true
    */

    p1:{
        value:'llaaa',
        enumerable:false,       //*
    },
    p2:{
        value:56,
        enumerable:true,
        configurable:true,
        writable:true,
    }
});
for(let i in obj){  //让i拥有obj的值
    console.log(i,obj2[i]);     //打印出p1 llaaa, p2 56
}
</script>
</html>

eg:8.enumerable
效果如下:


22.8enumerable.jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>

</body>
<script>
var obj = {
    a:'a',
    b:'b',
    c:'c',
};
for(let i in obj){  //让i拥有obj的值
    console.log(i,obj[i]);
}
console.log('___________________________')
Object.defineProperty(obj,'c',{
    value:13,
    //可枚举性(enumerable)用来控制所描述的属性,是否将被包括在for...in循环之中。一般enumerable后面跟的值true
    enumerable:false,
});
for(let i in obj){
    console.log(i,obj[i]);
}
</script>
</html>
9.(2)Object.getPrototypeOf(obj)

获取obj对象实例的原型
eg:9Object.getPrototypeOf
效果如下:


22.9getprototypeof.jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>

</body>
<script>
function A(name){
    this.name = name;
}
let a = new A('lili');
console.log(Object.getPrototypeOf(a));  //获取对象原型
console.log(a.__proto__)
Object.getPrototypeOf({}) === Object.prototype  //true
//new Object 与Object的原型是一致的。对象的原型与构造函数的原型是一致的。

Object.getPrototypeOf({})===null

//Object对象的原型的原型指向null。null也是原型链的顶点。

function f(){}
    Object.getPrototypeOf(f)===Function.prototype  //true
//构造函数的原型与内置对象function的原型相同。f=== new Function();

</script>
</html>
9.(3)Object.prototype.isPrototypeOf() 判断该对象是否为参数对象的原型

eg:console.log(Array.prototype.isPrototypeOf(b));

obj1.isPrototypeOf(obj2)
判断obj2的原型是否是obj1。

9.(4)Object.setPrototypeOf(obj)设置obj对象实例的原型

eg:10setPrototypeOf
效果如下:


22.10Object.setPrototypeOf.jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>

</body>
<script>
let a = new Array();
//Object.getPrototypeOf(obj)获取obj对象实例的原型
console.log(Object.getPrototypeOf(a));
//Object.setPrototypeOf(obj)设置obj对象实例的原型
Object.setPrototypeOf(a,Number.prototype);

console.log(Object.getPrototypeOf(a));
</script>
</html>
9.(5)Object.getOwnPropertyNames() 成员是参数对象本身的所有属性的键名,不包含继承的属性键名。

eg:12Object.getOwnPropertyNames()
效果如下:


22.12Object.getOwnPropertyNames().jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>

</body>
<script>
function A(name){
    this.name=name;
    this.say = function(){
        console.log(a);
    }
}
A.prototype.ss = function(){
    console.log('ss');
}

function B(name){
    A.call(this);
        this.age = 16,
        this.sex = 'man'

};
for(let i in A.prototype){
    B.prototype[i] = A.prototype[i];
}
let b = new B ('lala');
b.ss();
//Object.getOwnPropertyNames()    成员是参数对象本身的所有属性的键名,不包含继承的属性键名。
console.log(B.prototype.hasOwnProperty('say'));     //ss  false
</script>
</html>
9.(6)Object.prototype.hasOwnProperty() 用于判断某个属性定义在对象自身,还是定义在原型链上。
10.函数属性的区别:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>

</body>
<script>
function F(name){
    A.call(this);   
    B.call(this);      //此处的A.call 与B.call是属于实例函数   这种方式定义的属性,只能通过类的实例访问.不同实例之间共享该属性;不能通过 类名.属性名的方式访问
    let ll = name ;   //私有成员  此处的‘ll’是私有属性私有属性  在对象的定义中定义的非全局变量这种方式定义的属性,类的实例不能访问;只能通过 类名.属性名访问
    this.getName = function(){
        console.log(ll);
    }
}

let f = new F('lili');

f.getName();
</script>
</html>
11.命名空间

eg:14命名空间

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>

</body>
<script>
//适用于大型项目组


//在所有的调用函数前设置一个qq的命名,让所有的要调用的函数都包含在qq中以避免与项目组的成员之间的项目函数调用重名
var qq= {
    this.F = function(){

    }
    this.S = function(){

    }
};

li.F()
</script>
</html>
上一篇下一篇

猜你喜欢

热点阅读